summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/common/AnnotationCheckers.scala120
-rw-r--r--src/compiler/scala/reflect/common/AnnotationInfos.scala143
-rw-r--r--src/compiler/scala/reflect/common/BaseTypeSeqs.scala251
-rw-r--r--src/compiler/scala/reflect/common/Caches.scala103
-rw-r--r--src/compiler/scala/reflect/common/ClassfileConstants.scala332
-rw-r--r--src/compiler/scala/reflect/common/Constants.scala238
-rw-r--r--src/compiler/scala/reflect/common/Definitions.scala (renamed from src/compiler/scala/tools/nsc/symtab/Definitions.scala)10
-rw-r--r--src/compiler/scala/reflect/common/Flags.scala2
-rw-r--r--src/compiler/scala/reflect/common/HasFlags.scala231
-rw-r--r--src/compiler/scala/reflect/common/InfoTransformers.scala47
-rw-r--r--src/compiler/scala/reflect/common/NameManglers.scala172
-rw-r--r--src/compiler/scala/reflect/common/Names.scala434
-rw-r--r--src/compiler/scala/reflect/common/Positions.scala33
-rw-r--r--src/compiler/scala/reflect/common/Required.scala17
-rw-r--r--src/compiler/scala/reflect/common/Scopes.scala326
-rw-r--r--src/compiler/scala/reflect/common/StdNames.scala617
-rw-r--r--src/compiler/scala/reflect/common/SymbolTable.scala112
-rw-r--r--src/compiler/scala/reflect/common/Symbols.scala2275
-rw-r--r--src/compiler/scala/reflect/common/TreeGen.scala234
-rw-r--r--src/compiler/scala/reflect/common/TreeInfo.scala (renamed from src/compiler/scala/tools/nsc/ast/TreeInfo.scala)8
-rw-r--r--src/compiler/scala/reflect/common/TreePrinters.scala461
-rw-r--r--src/compiler/scala/reflect/common/Trees.scala1823
-rw-r--r--src/compiler/scala/reflect/common/TypeDebugging.scala72
-rw-r--r--src/compiler/scala/reflect/common/Types.scala5699
-rw-r--r--src/compiler/scala/reflect/common/pickling/UnPickler.scala841
-rw-r--r--src/compiler/scala/reflect/common/util/Chars.scala92
-rw-r--r--src/compiler/scala/reflect/std/JavaMappings.scala62
-rw-r--r--src/compiler/scala/reflect/std/Mirror.scala14
-rw-r--r--src/compiler/scala/reflect/std/Positions.scala13
-rw-r--r--src/compiler/scala/reflect/std/ReflectSettings.scala23
-rw-r--r--src/compiler/scala/reflect/std/SymbolCompleters.scala80
-rw-r--r--src/compiler/scala/tools/cmd/program/Tokens.scala2
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/CompileServer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/FatalError.scala19
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala35
-rw-r--r--src/compiler/scala/tools/nsc/NoPhase.scala11
-rw-r--r--src/compiler/scala/tools/nsc/Phase.scala85
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala229
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala432
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala1150
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala11
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala2
-rw-r--r--src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala6
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala5
-rw-r--r--src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala7
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/AbsSettings.scala8
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala18
-rw-r--r--src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala120
-rw-r--r--src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala152
-rw-r--r--src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala251
-rw-r--r--src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Caches.scala103
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala220
-rw-r--r--src/compiler/scala/tools/nsc/symtab/InfoTransformers.scala47
-rw-r--r--src/compiler/scala/tools/nsc/symtab/NameManglers.scala172
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Names.scala429
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Positions.scala28
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Scopes.scala336
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala589
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala105
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala2181
-rw-r--r--src/compiler/scala/tools/nsc/symtab/TypeDebugging.scala72
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala5674
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala9
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala77
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Reifiers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala6
82 files changed, 14879 insertions, 12641 deletions
diff --git a/src/compiler/scala/reflect/common/AnnotationCheckers.scala b/src/compiler/scala/reflect/common/AnnotationCheckers.scala
new file mode 100644
index 0000000000..cd3b343238
--- /dev/null
+++ b/src/compiler/scala/reflect/common/AnnotationCheckers.scala
@@ -0,0 +1,120 @@
+/* NSC -- new Scala compiler
+ * Copyright 2007-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+/** Additions to the type checker that can be added at
+ * run time. Typically these are added by
+ * compiler plugins. */
+trait AnnotationCheckers {
+ self: SymbolTable =>
+
+
+ /** An additional checker for annotations on types.
+ * Typically these are registered by compiler plugins
+ * with the addAnnotationChecker method. */
+ abstract class AnnotationChecker {
+ /** Check the annotations on two types conform. */
+ def annotationsConform(tpe1: Type, tpe2: Type): Boolean
+
+ /** Refine the computed least upper bound of a list of types.
+ * All this should do is add annotations. */
+ def annotationsLub(tp: Type, ts: List[Type]): Type = tp
+
+ /** Refine the computed greatest lower bound of a list of types.
+ * All this should do is add annotations. */
+ def annotationsGlb(tp: Type, ts: List[Type]): Type = tp
+
+ /** Refine the bounds on type parameters to the given type arguments. */
+ def adaptBoundsToAnnotations(bounds: List[TypeBounds],
+ tparams: List[Symbol], targs: List[Type]): List[TypeBounds] = bounds
+
+ /** Modify the type that has thus far been inferred
+ * for a tree. All this should do is add annotations. */
+ def addAnnotations(tree: Tree, tpe: Type): Type = tpe
+
+ /** Decide whether this annotation checker can adapt a tree
+ * that has an annotated type to the given type tp, taking
+ * into account the given mode (see method adapt in trait Typers).*/
+ def canAdaptAnnotations(tree: Tree, mode: Int, pt: Type): Boolean = false
+
+ /** Adapt a tree that has an annotated type to the given type tp,
+ * taking into account the given mode (see method adapt in trait Typers).
+ * An implementation cannot rely on canAdaptAnnotations being called
+ * before. If the implementing class cannot do the adaptiong, it
+ * should return the tree unchanged.*/
+ def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = tree
+ }
+
+ /** The list of annotation checkers that have been registered */
+ private var annotationCheckers: List[AnnotationChecker] = Nil
+
+ /** Register an annotation checker. Typically these
+ * are added by compiler plugins. */
+ def addAnnotationChecker(checker: AnnotationChecker) {
+ if (!(annotationCheckers contains checker))
+ annotationCheckers = checker :: annotationCheckers
+ }
+
+ /** Remove all annotation checkers */
+ def removeAllAnnotationCheckers() {
+ annotationCheckers = Nil
+ }
+
+ /** Check that the annotations on two types conform. To do
+ * so, consult all registered annotation checkers. */
+ def annotationsConform(tp1: Type, tp2: Type): Boolean = {
+ /* Finish quickly if there are no annotations */
+ if (tp1.annotations.isEmpty && tp2.annotations.isEmpty)
+ true
+ else
+ annotationCheckers.forall(
+ _.annotationsConform(tp1,tp2))
+ }
+
+ /** Refine the computed least upper bound of a list of types.
+ * All this should do is add annotations. */
+ def annotationsLub(tpe: Type, ts: List[Type]): Type = {
+ annotationCheckers.foldLeft(tpe)((tpe, checker) =>
+ checker.annotationsLub(tpe, ts))
+ }
+
+ /** Refine the computed greatest lower bound of a list of types.
+ * All this should do is add annotations. */
+ def annotationsGlb(tpe: Type, ts: List[Type]): Type = {
+ annotationCheckers.foldLeft(tpe)((tpe, checker) =>
+ checker.annotationsGlb(tpe, ts))
+ }
+
+ /** Refine the bounds on type parameters to the given type arguments. */
+ def adaptBoundsToAnnotations(bounds: List[TypeBounds],
+ tparams: List[Symbol], targs: List[Type]): List[TypeBounds] = {
+ annotationCheckers.foldLeft(bounds)((bounds, checker) =>
+ checker.adaptBoundsToAnnotations(bounds, tparams, targs))
+ }
+
+ /** Let all annotations checkers add extra annotations
+ * to this tree's type. */
+ def addAnnotations(tree: Tree, tpe: Type): Type = {
+ annotationCheckers.foldLeft(tpe)((tpe, checker) =>
+ checker.addAnnotations(tree, tpe))
+ }
+
+ /** Find out whether any annotation checker can adapt a tree
+ * to a given type. Called by Typers.adapt. */
+ def canAdaptAnnotations(tree: Tree, mode: Int, pt: Type): Boolean = {
+ annotationCheckers.exists(_.canAdaptAnnotations(tree, mode, pt))
+ }
+
+ /** Let registered annotation checkers adapt a tree
+ * to a given type (called by Typers.adapt). Annotation checkers
+ * that cannot do the adaption should pass the tree through
+ * unchanged. */
+ def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = {
+ annotationCheckers.foldLeft(tree)((tree, checker) =>
+ checker.adaptAnnotations(tree, mode, pt))
+ }
+}
diff --git a/src/compiler/scala/reflect/common/AnnotationInfos.scala b/src/compiler/scala/reflect/common/AnnotationInfos.scala
new file mode 100644
index 0000000000..642e2f0b22
--- /dev/null
+++ b/src/compiler/scala/reflect/common/AnnotationInfos.scala
@@ -0,0 +1,143 @@
+/* NSC -- new Scala compiler
+ * Copyright 2007-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+import util._
+
+/** AnnotationInfo and its helpers */
+trait AnnotationInfos /*extends reflect.generic.AnnotationInfos*/ { self: SymbolTable =>
+
+ /** Arguments to classfile annotations (which are written to
+ * bytecode as java annotations) are either:
+ * <ul>
+ * <li>constants</li>
+ * <li>arrays of constants</li>
+ * <li>or nested classfile annotations</li>
+ * </ul>
+ */
+ abstract class ClassfileAnnotArg
+
+ /** Represents a compile-time Constant (Boolean, Byte, Short,
+ * Char, Int, Long, Float, Double, String, java.lang.Class or
+ * an instance of a Java enumeration value).
+ */
+ case class LiteralAnnotArg(const: Constant)
+ extends ClassfileAnnotArg {
+ override def toString = const.escapedStringValue
+ }
+
+ /** Represents an array of classfile annotation arguments */
+ case class ArrayAnnotArg(args: Array[ClassfileAnnotArg])
+ extends ClassfileAnnotArg {
+ override def toString = args.mkString("[", ", ", "]")
+ }
+
+ /** A specific annotation argument that encodes an array of bytes as an array of `Long`. The type of the argument
+ * declared in the annotation must be `String`. This specialised class is used to encode scala signatures for
+ * reasons of efficiency, both in term of class-file size and in term of compiler performance. */
+ case class ScalaSigBytes(bytes: Array[Byte]) extends ClassfileAnnotArg {
+ override def toString = (bytes map { byte => (byte & 0xff).toHexString }).mkString("[ ", " ", " ]")
+ lazy val encodedBytes =
+ reflect.generic.ByteCodecs.encode(bytes)
+ def isLong: Boolean = (encodedBytes.length > 65535)
+ def sigAnnot: Type =
+ if (this.isLong)
+ definitions.ScalaLongSignatureAnnotation.tpe
+ else
+ definitions.ScalaSignatureAnnotation.tpe
+ }
+
+ /** Represents a nested classfile annotation */
+ case class NestedAnnotArg(annInfo: AnnotationInfo)
+ extends ClassfileAnnotArg {
+ // The nested annotation should not have any Scala annotation arguments
+ assert(annInfo.args.isEmpty, annInfo.args)
+ override def toString = annInfo.toString
+ }
+
+ class AnnotationInfoBase
+
+ /** <p>
+ * Typed information about an annotation. It can be attached to
+ * either a symbol or an annotated type.
+ * </p>
+ * <p>
+ * Annotations are written to the classfile as java annotations
+ * if <code>atp</code> conforms to <code>ClassfileAnnotation</code>
+ * (the classfile parser adds this interface to any Java annotation
+ * class).
+ * </p>
+ * <p>
+ * Annotations are pickled (written to scala symtab attribute
+ * in the classfile) if <code>atp</code> inherits form
+ * <code>StaticAnnotation</code>.
+ * </p>
+ * <p>
+ * <code>args</code> stores arguments to Scala annotations,
+ * represented as typed trees. Note that these trees are not
+ * transformed by any phases following the type-checker.
+ * </p>
+ * <p>
+ * <code>assocs</code> stores arguments to classfile annotations
+ * as name-value pairs.
+ * </p>
+ */
+ case class AnnotationInfo(atp: Type, args: List[Tree],
+ assocs: List[(Name, ClassfileAnnotArg)])
+ extends AnnotationInfoBase {
+
+ // Classfile annot: args empty. Scala annot: assocs empty.
+ assert(args.isEmpty || assocs.isEmpty)
+
+ private var rawpos: Position = NoPosition
+ def pos = rawpos
+ def setPos(pos: Position): this.type = {
+ rawpos = pos
+ this
+ }
+
+ lazy val isTrivial: Boolean = atp.isTrivial && !(args exists (_.exists(_.isInstanceOf[This]))) // see annotationArgRewriter
+
+ override def toString: String = atp +
+ (if (!args.isEmpty) args.mkString("(", ", ", ")") else "") +
+ (if (!assocs.isEmpty) (assocs map { case (x, y) => x+" = "+y } mkString ("(", ", ", ")")) else "")
+
+ /** Check whether the type or any of the arguments are erroneous */
+ def isErroneous = atp.isErroneous || args.exists(_.isErroneous)
+
+ /** Check whether any of the arguments mention a symbol */
+ def refsSymbol(sym: Symbol) =
+ args.exists(_.exists(_.symbol == sym))
+
+ /** Change all ident's with Symbol "from" to instead use symbol "to" */
+ def substIdentSyms(from: Symbol, to: Symbol) = {
+ val subs = new TreeSymSubstituter(List(from), List(to))
+ AnnotationInfo(atp, args.map(subs(_)), assocs).setPos(pos)
+ }
+
+ // !!! when annotation arguments are not literal strings, but any sort of
+ // assembly of strings, there is a fair chance they will turn up here not as
+ // Literal(const) but some arbitrary AST.
+ def stringArg(index: Int): Option[String] = if(args.size > index) Some(args(index) match {
+ case Literal(const) => const.stringValue
+ case x => x.toString // should not be necessary, but better than silently ignoring an issue
+ }) else None
+
+ def intArg(index: Int): Option[Int] = if(args.size > index) Some(args(index)) collect {
+ case Literal(Constant(x: Int)) => x
+ } else None
+ }
+
+ lazy val classfileAnnotArgManifest: ClassManifest[ClassfileAnnotArg] =
+ reflect.ClassManifest.classType(classOf[ClassfileAnnotArg])
+
+ /** Symbol annotations parsed in Namer (typeCompleter of
+ * definitions) have to be lazy (#1782)
+ */
+ case class LazyAnnotationInfo(annot: () => AnnotationInfo)
+ extends AnnotationInfoBase
+}
diff --git a/src/compiler/scala/reflect/common/BaseTypeSeqs.scala b/src/compiler/scala/reflect/common/BaseTypeSeqs.scala
new file mode 100644
index 0000000000..7a77ca8e62
--- /dev/null
+++ b/src/compiler/scala/reflect/common/BaseTypeSeqs.scala
@@ -0,0 +1,251 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+package scala.reflect
+package common
+
+// todo implement in terms of BitSet
+import scala.collection.mutable.{ListBuffer, BitSet}
+import math.max
+import util.Statistics._
+
+/** A base type sequence (BaseTypeSeq) is an ordered sequence spanning all the base types
+ * of a type. It characterized by the following two laws:
+ *
+ * (1) Each element of `tp.baseTypeSeq' is a basetype of `tp'
+ * (2) For each basetype `bt1' of `tp' there is an element `bt' in `tp.baseTypeSeq' such that
+ *
+ * bt.typeSymbol = bt1.typeSymbol
+ * bt <: bt1
+ *
+ * (3) The type symbols of different elements are different.
+ *
+ * Elements in the sequence are ordered by Symbol.isLess.
+ * @note base type sequences were called closures up to 2.7.1. The name has been changed
+ * to avoid confusion with function closures.
+ */
+trait BaseTypeSeqs {
+ this: SymbolTable =>
+ import definitions._
+
+ class BaseTypeSeq(parents: List[Type], elems: Array[Type]) {
+ self =>
+ incCounter(baseTypeSeqCount)
+ incCounter(baseTypeSeqLenTotal, elems.length)
+
+ /** The number of types in the sequence */
+ def length: Int = elems.length
+
+ // #3676 shows why we can't store NoType in elems to mark cycles
+ // (while NoType is in there to indicate a cycle in this BTS, during the execution of
+ // the mergePrefixAndArgs below, the elems get copied without the pending map,
+ // so that NoType's are seen instead of the original type --> spurious compile error)
+ val pending = new BitSet(length)
+
+ /** The type at i'th position in this sequence; lazy types are returned evaluated. */
+ def apply(i: Int): Type =
+ if(pending contains i) {
+ pending.clear()
+ throw CyclicInheritance
+ } else
+ elems(i) match {
+ case rtp @ RefinedType(variants, decls) =>
+ // can't assert decls.isEmpty; see t0764
+ //if (!decls.isEmpty) assert(false, "computing closure of "+this+":"+this.isInstanceOf[RefinedType]+"/"+closureCache(j))
+ //Console.println("compute closure of "+this+" => glb("+variants+")")
+ pending += i
+ try {
+ mergePrefixAndArgs(variants, -1, lubDepth(variants)) match {
+ case Some(tp0) =>
+ pending(i) = false
+ elems(i) = tp0
+ tp0
+ case None =>
+ typeError(
+ "no common type instance of base types "+(variants mkString ", and ")+" exists.")
+ }
+ } catch {
+ case CyclicInheritance =>
+ typeError(
+ "computing the common type instance of base types "+(variants mkString ", and ")+" leads to a cycle.")
+ }
+ case tp =>
+ tp
+ }
+
+ def rawElem(i: Int) = elems(i)
+
+ /** The type symbol of the type at i'th position in this sequence;
+ * no evaluation needed.
+ */
+ def typeSymbol(i: Int): Symbol = {
+ elems(i) match {
+ case RefinedType(v :: vs, _) => v.typeSymbol
+ case tp => tp.typeSymbol
+ }
+ }
+
+ /** Return all evaluated types in this sequence as a list */
+ def toList: List[Type] = elems.toList
+
+ protected def copy(head: Type, offset: Int): BaseTypeSeq = {
+ val arr = new Array[Type](elems.length + offset)
+ compat.Platform.arraycopy(elems, 0, arr, offset, elems.length)
+ arr(0) = head
+ new BaseTypeSeq(parents, arr)
+ }
+
+ /** Compute new base type sequence with `tp' prepended to this sequence */
+ def prepend(tp: Type): BaseTypeSeq = copy(tp, 1)
+
+ /** Compute new base type sequence with `tp' replacing the head of this sequence */
+ def updateHead(tp: Type): BaseTypeSeq = copy(tp, 0)
+
+ /** Compute new base type sequence where every element is mapped
+ * with function `f'. Lazy types are mapped but not evaluated */
+ def map(f: Type => Type): BaseTypeSeq = {
+ // inlined `elems map f' for performance
+ val len = length
+ var arr = new Array[Type](len)
+ var i = 0
+ while (i < len) {
+ arr(i) = f(elems(i))
+ i += 1
+ }
+ new BaseTypeSeq(parents, arr)
+ }
+
+ def lateMap(f: Type => Type): BaseTypeSeq = new BaseTypeSeq(parents map f, elems) {
+ override def apply(i: Int) = f(self.apply(i))
+ override def rawElem(i: Int) = f(self.rawElem(i))
+ override def typeSymbol(i: Int) = self.typeSymbol(i)
+ override def toList = self.toList map f
+ override protected def copy(head: Type, offset: Int) = (self map f).copy(head, offset)
+ override def map(g: Type => Type) = lateMap(g)
+ override def lateMap(g: Type => Type) = self.lateMap(x => g(f(x)))
+ override def exists(p: Type => Boolean) = elems exists (x => p(f(x)))
+ override protected def maxDepthOfElems: Int = elems map (x => maxDpth(f(x))) max
+ override def toString = elems.mkString("MBTS(", ",", ")")
+ }
+
+ def exists(p: Type => Boolean): Boolean = elems exists p
+
+ lazy val maxDepth: Int = maxDepthOfElems
+
+ protected def maxDepthOfElems = {
+ var d = 0
+ for (i <- 0 until length) d = max(d, maxDpth(elems(i)))
+ d
+ }
+
+ /** The maximum depth of type `tp' */
+ protected def maxDpth(tp: Type): Int = tp match {
+ case TypeRef(pre, sym, args) =>
+ max(maxDpth(pre), maxDpth(args) + 1)
+ case RefinedType(parents, decls) =>
+ max(maxDpth(parents), maxDpth(decls.toList.map(_.info)) + 1)
+ case TypeBounds(lo, hi) =>
+ max(maxDpth(lo), maxDpth(hi))
+ case MethodType(paramtypes, result) =>
+ maxDpth(result)
+ case NullaryMethodType(result) =>
+ maxDpth(result)
+ case PolyType(tparams, result) =>
+ max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
+ case ExistentialType(tparams, result) =>
+ max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
+ case _ =>
+ 1
+ }
+
+ /** The maximum depth of all types `tps' */
+ private def maxDpth(tps: Seq[Type]): Int = {
+ var d = 0
+ for (tp <- tps) d = max(d, maxDpth(tp))
+ d
+ }
+
+ override def toString = elems.mkString("BTS(", ",", ")")
+
+ private def typeError(msg: String): Nothing =
+ throw new TypeError(
+ "the type intersection "+(parents mkString " with ")+" is malformed"+
+ "\n --- because ---\n"+msg)
+ }
+
+ /** A merker object for a base type sequence that's no yet computed.
+ * used to catch inheritance cycles
+ */
+ val undetBaseTypeSeq: BaseTypeSeq = new BaseTypeSeq(List(), Array())
+
+ /** Create a base type sequence consisting of a single type */
+ def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = new BaseTypeSeq(List(), Array(tp))
+
+ /** Create the base type sequence of a compound type wuth given tp.parents */
+ def compoundBaseTypeSeq(tp: Type): BaseTypeSeq = {
+ val tsym = tp.typeSymbol
+ val parents = tp.parents
+// Console.println("computing baseTypeSeq of " + tsym.tpe + " " + parents)//DEBUG
+ val buf = new ListBuffer[Type]
+ buf += tsym.tpe
+ var btsSize = 1
+ if (parents.nonEmpty) {
+ val nparents = parents.length
+ val pbtss = new Array[BaseTypeSeq](nparents)
+ val index = new Array[Int](nparents)
+ var i = 0
+ for (p <- parents) {
+ pbtss(i) =
+ if (p.baseTypeSeq eq undetBaseTypeSeq) AnyClass.info.baseTypeSeq
+ else p.baseTypeSeq
+ index(i) = 0
+ i += 1
+ }
+ def nextTypeSymbol(i: Int): Symbol = {
+ val j = index(i)
+ val pbts = pbtss(i)
+ if (j < pbts.length) pbts.typeSymbol(j) else AnyClass
+ }
+ def nextRawElem(i: Int): Type = {
+ val j = index(i)
+ val pbts = pbtss(i)
+ if (j < pbts.length) pbts.rawElem(j) else AnyClass.tpe
+ }
+ var minSym: Symbol = NoSymbol
+ while (minSym != AnyClass) {
+ minSym = nextTypeSymbol(0)
+ i = 1
+ while (i < nparents) {
+ val nextSym = nextTypeSymbol(i)
+ if (nextSym isLess minSym)
+ minSym = nextSym
+ i += 1
+ }
+ var minTypes: List[Type] = List()
+ i = 0
+ while (i < nparents) {
+ if (nextTypeSymbol(i) == minSym) {
+ nextRawElem(i) match {
+ case RefinedType(variants, decls) =>
+ for (tp <- variants)
+ if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes
+ case tp =>
+ if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes
+ }
+ index(i) = index(i) + 1
+ }
+ i += 1
+ }
+ buf += intersectionType(minTypes)
+ btsSize += 1
+ }
+ }
+ val elems = new Array[Type](btsSize)
+ buf.copyToArray(elems, 0)
+// Console.println("computed baseTypeSeq of " + tsym.tpe + " " + parents + ": "+elems.toString)//DEBUG
+ new BaseTypeSeq(parents, elems)
+ }
+
+ val CyclicInheritance = new Throwable
+}
diff --git a/src/compiler/scala/reflect/common/Caches.scala b/src/compiler/scala/reflect/common/Caches.scala
new file mode 100644
index 0000000000..2666761f92
--- /dev/null
+++ b/src/compiler/scala/reflect/common/Caches.scala
@@ -0,0 +1,103 @@
+/* NSC -- new scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.reflect
+package common
+
+import scala.collection.{ mutable, immutable }
+
+/** A cache for some entity whose validity depends on a monotonically
+ * increasing sequence number.
+ */
+abstract class SequencedCache[T >: Null] {
+ def zero: Int
+ def sequenceId: Int
+ def calculate(): T
+
+ /** If sequence numbers differ, this condition is consulted before
+ * updating the cached value.
+ */
+ def isCacheValid: Boolean
+
+ /** Public so accesses can be inlined. */
+ @inline var cachedId: Int = 0
+ @inline var cachedValue: T = _
+
+ /** Puts cache back in uninitialized state. */
+ @inline final def clear() = {
+ cachedId = zero
+ cachedValue = null
+ }
+ /** Resets the sequence id without touching the cached value. */
+ @inline final def reset() = {
+ cachedId = zero
+ }
+
+ final def get(): T = {
+ if (cachedValue == null) {
+ cachedValue = calculate()
+ cachedId = sequenceId
+ }
+ else if (cachedId != sequenceId) {
+ if (!isCacheValid)
+ cachedValue = calculate()
+
+ cachedId = sequenceId
+ }
+ cachedValue
+ }
+}
+
+trait Caches {
+ self: SymbolTable =>
+
+ final def isValid(period: Period): Boolean =
+ period != 0 && runId(period) == currentRunId && {
+ val pid = phaseId(period)
+ if (phase.id > pid) infoTransformers.nextFrom(pid).pid >= phase.id
+ else infoTransformers.nextFrom(phase.id).pid >= pid
+ }
+
+ final def isValidForBaseClasses(period: Period): Boolean = {
+ def noChangeInBaseClasses(it: InfoTransformer, limit: Phase#Id): Boolean = (
+ it.pid >= limit ||
+ !it.changesBaseClasses && noChangeInBaseClasses(it.next, limit)
+ );
+ period != 0 && runId(period) == currentRunId && {
+ val pid = phaseId(period)
+ if (phase.id > pid) noChangeInBaseClasses(infoTransformers.nextFrom(pid), phase.id)
+ else noChangeInBaseClasses(infoTransformers.nextFrom(phase.id), pid)
+ }
+ }
+
+ abstract class PeriodCache[T >: Null] extends SequencedCache[T] {
+ final val zero = NoPeriod
+ @inline final def sequenceId = currentPeriod
+ }
+
+ abstract class ListOfTypesCache extends PeriodCache[List[Type]] {
+ @inline final def isCacheValid = isValidForBaseClasses(cachedId)
+ }
+ abstract class ListOfSymbolsCache extends PeriodCache[List[Symbol]] {
+ @inline final def isCacheValid = isValidForBaseClasses(cachedId)
+ }
+ abstract class BaseTypeSeqCache extends PeriodCache[BaseTypeSeq] {
+ @inline final def isCacheValid = isValidForBaseClasses(cachedId)
+ }
+ abstract class TypeCache extends PeriodCache[Type] {
+ @inline final def isCacheValid = isValid(cachedId)
+ }
+ abstract class TypeCacheForRunId extends SequencedCache[Type] {
+ final val zero = NoRunId
+ @inline final def sequenceId = currentRunId
+ @inline final override def isCacheValid = false
+ }
+ object TypeCache {
+ def apply(body: => Type): TypeCache = new TypeCache {
+ @inline final def calculate() = body
+ }
+ }
+}
+
diff --git a/src/compiler/scala/reflect/common/ClassfileConstants.scala b/src/compiler/scala/reflect/common/ClassfileConstants.scala
new file mode 100644
index 0000000000..a48b16be96
--- /dev/null
+++ b/src/compiler/scala/reflect/common/ClassfileConstants.scala
@@ -0,0 +1,332 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+object ClassfileConstants {
+
+ final val JAVA_MAGIC = 0xCAFEBABE
+ final val JAVA_MAJOR_VERSION = 45
+ final val JAVA_MINOR_VERSION = 3
+
+ /** <p>
+ * (see http://java.sun.com/docs/books/jvms/second_edition/jvms-clarify.html)
+ * </p>
+ * <p>
+ * If the <code>ACC_INTERFACE</code> flag is set, the <code>ACC_ABSTRACT</code>
+ * flag must also be set (ch. 2.13.1).
+ * </p>
+ * <p>
+ * A class file cannot have both its <code>ACC_FINAL</code> and
+ * <code>ACC_ABSTRACT</code> flags set (ch. 2.8.2).
+ * </p>
+ * <p>
+ * A field may have at most one of its <code>ACC_PRIVATE</code>,
+ * <code>ACC_PROTECTED</code>, <code>ACC_PUBLIC</code> flags set (ch. 2.7.4).
+ * </p>
+ * <p>
+ * A field may not have both its <code>ACC_FINAL</code> and
+ * <code>ACC_VOLATILE</code> flags set (ch. 2.9.1).
+ * </p>
+ * <p>
+ * If a method has its <code>ACC_ABSTRACT</code> flag set it must not
+ * have any of its <code>ACC_FINAL</code>, <code>ACC_NATIVE</code>,
+ * <code>ACC_PRIVATE</code>, <code>ACC_STATIC</code>, <code>ACC_STRICT</code>,
+ * or <code>ACC_SYNCHRONIZED</code> flags set (ch. 2.13.3.2).
+ * </p>
+ * <p>
+ * All interface methods must have their <code>ACC_ABSTRACT</code> and
+ * <code>ACC_PUBLIC</code> flags set.
+ * </p>
+ */ // Class Field Method
+ final val JAVA_ACC_PUBLIC = 0x0001 // X X X
+ final val JAVA_ACC_PRIVATE = 0x0002 // X X
+ final val JAVA_ACC_PROTECTED = 0x0004 // X X
+ final val JAVA_ACC_STATIC = 0x0008 // X X
+ final val JAVA_ACC_FINAL = 0x0010 // X X X
+ final val JAVA_ACC_SUPER = 0x0020 // X
+ final val JAVA_ACC_SYNCHRONIZED = 0x0020 // X
+ final val JAVA_ACC_VOLATILE = 0x0040 // X
+ final val JAVA_ACC_BRIDGE = 0x0040 // X
+ final val JAVA_ACC_TRANSIENT = 0x0080 // X
+ final val JAVA_ACC_VARARGS = 0x0080 // X
+ final val JAVA_ACC_NATIVE = 0x0100 // X
+ final val JAVA_ACC_INTERFACE = 0x0200 // X
+ final val JAVA_ACC_ABSTRACT = 0x0400 // X X
+ final val JAVA_ACC_STRICT = 0x0800 // X
+ final val JAVA_ACC_SYNTHETIC = 0x1000 // X X X
+ final val JAVA_ACC_ANNOTATION = 0x2000 // X
+ final val JAVA_ACC_ENUM = 0x4000 // X X
+
+ // tags describing the type of a literal in the constant pool
+ final val CONSTANT_UTF8 = 1
+ final val CONSTANT_UNICODE = 2
+ final val CONSTANT_INTEGER = 3
+ final val CONSTANT_FLOAT = 4
+ final val CONSTANT_LONG = 5
+ final val CONSTANT_DOUBLE = 6
+ final val CONSTANT_CLASS = 7
+ final val CONSTANT_STRING = 8
+ final val CONSTANT_FIELDREF = 9
+ final val CONSTANT_METHODREF = 10
+ final val CONSTANT_INTFMETHODREF = 11
+ final val CONSTANT_NAMEANDTYPE = 12
+
+ // tags describing the type of a literal in attribute values
+ final val BYTE_TAG = 'B'
+ final val CHAR_TAG = 'C'
+ final val DOUBLE_TAG = 'D'
+ final val FLOAT_TAG = 'F'
+ final val INT_TAG = 'I'
+ final val LONG_TAG = 'J'
+ final val SHORT_TAG = 'S'
+ final val BOOL_TAG = 'Z'
+ final val STRING_TAG = 's'
+ final val ENUM_TAG = 'e'
+ final val CLASS_TAG = 'c'
+ final val ARRAY_TAG = '['
+ final val VOID_TAG = 'V'
+ final val TVAR_TAG = 'T'
+ final val ANNOTATION_TAG = '@'
+ final val SCALA_NOTHING = "scala.runtime.Nothing$"
+ final val SCALA_NULL = "scala.runtime.Null$"
+
+
+ // tags describing the type of newarray
+ final val T_BOOLEAN = 4
+ final val T_CHAR = 5
+ final val T_FLOAT = 6
+ final val T_DOUBLE = 7
+ final val T_BYTE = 8
+ final val T_SHORT = 9
+ final val T_INT = 10
+ final val T_LONG = 11
+
+ // JVM mnemonics
+ final val nop = 0x00
+ final val aconst_null = 0x01
+ final val iconst_m1 = 0x02
+
+ final val iconst_0 = 0x03
+ final val iconst_1 = 0x04
+ final val iconst_2 = 0x05
+ final val iconst_3 = 0x06
+ final val iconst_4 = 0x07
+ final val iconst_5 = 0x08
+
+ final val lconst_0 = 0x09
+ final val lconst_1 = 0x0a
+ final val fconst_0 = 0x0b
+ final val fconst_1 = 0x0c
+ final val fconst_2 = 0x0d
+ final val dconst_0 = 0x0e
+ final val dconst_1 = 0x0f
+
+ final val bipush = 0x10
+ final val sipush = 0x11
+ final val ldc = 0x12
+ final val ldc_w = 0x13
+ final val ldc2_w = 0x14
+
+ final val iload = 0x15
+ final val lload = 0x16
+ final val fload = 0x17
+ final val dload = 0x18
+ final val aload = 0x19
+
+ final val iload_0 = 0x1a
+ final val iload_1 = 0x1b
+ final val iload_2 = 0x1c
+ final val iload_3 = 0x1d
+ final val lload_0 = 0x1e
+ final val lload_1 = 0x1f
+ final val lload_2 = 0x20
+ final val lload_3 = 0x21
+ final val fload_0 = 0x22
+ final val fload_1 = 0x23
+ final val fload_2 = 0x24
+ final val fload_3 = 0x25
+ final val dload_0 = 0x26
+ final val dload_1 = 0x27
+ final val dload_2 = 0x28
+ final val dload_3 = 0x29
+ final val aload_0 = 0x2a
+ final val aload_1 = 0x2b
+ final val aload_2 = 0x2c
+ final val aload_3 = 0x2d
+ final val iaload = 0x2e
+ final val laload = 0x2f
+ final val faload = 0x30
+ final val daload = 0x31
+ final val aaload = 0x32
+ final val baload = 0x33
+ final val caload = 0x34
+ final val saload = 0x35
+
+ final val istore = 0x36
+ final val lstore = 0x37
+ final val fstore = 0x38
+ final val dstore = 0x39
+ final val astore = 0x3a
+ final val istore_0 = 0x3b
+ final val istore_1 = 0x3c
+ final val istore_2 = 0x3d
+ final val istore_3 = 0x3e
+ final val lstore_0 = 0x3f
+ final val lstore_1 = 0x40
+ final val lstore_2 = 0x41
+ final val lstore_3 = 0x42
+ final val fstore_0 = 0x43
+ final val fstore_1 = 0x44
+ final val fstore_2 = 0x45
+ final val fstore_3 = 0x46
+ final val dstore_0 = 0x47
+ final val dstore_1 = 0x48
+ final val dstore_2 = 0x49
+ final val dstore_3 = 0x4a
+ final val astore_0 = 0x4b
+ final val astore_1 = 0x4c
+ final val astore_2 = 0x4d
+ final val astore_3 = 0x4e
+ final val iastore = 0x4f
+ final val lastore = 0x50
+ final val fastore = 0x51
+ final val dastore = 0x52
+ final val aastore = 0x53
+ final val bastore = 0x54
+ final val castore = 0x55
+ final val sastore = 0x56
+
+ final val pop = 0x57
+ final val pop2 = 0x58
+ final val dup = 0x59
+ final val dup_x1 = 0x5a
+ final val dup_x2 = 0x5b
+ final val dup2 = 0x5c
+ final val dup2_x1 = 0x5d
+ final val dup2_x2 = 0x5e
+ final val swap = 0x5f
+
+ final val iadd = 0x60
+ final val ladd = 0x61
+ final val fadd = 0x62
+ final val dadd = 0x63
+ final val isub = 0x64
+ final val lsub = 0x65
+ final val fsub = 0x66
+ final val dsub = 0x67
+ final val imul = 0x68
+ final val lmul = 0x69
+ final val fmul = 0x6a
+ final val dmul = 0x6b
+ final val idiv = 0x6c
+ final val ldiv = 0x6d
+ final val fdiv = 0x6e
+ final val ddiv = 0x6f
+ final val irem = 0x70
+ final val lrem = 0x71
+ final val frem = 0x72
+ final val drem = 0x73
+
+ final val ineg = 0x74
+ final val lneg = 0x75
+ final val fneg = 0x76
+ final val dneg = 0x77
+
+ final val ishl = 0x78
+ final val lshl = 0x79
+ final val ishr = 0x7a
+ final val lshr = 0x7b
+ final val iushr = 0x7c
+ final val lushr = 0x7d
+ final val iand = 0x7e
+ final val land = 0x7f
+ final val ior = 0x80
+ final val lor = 0x81
+ final val ixor = 0x82
+ final val lxor = 0x83
+ final val iinc = 0x84
+
+ final val i2l = 0x85
+ final val i2f = 0x86
+ final val i2d = 0x87
+ final val l2i = 0x88
+ final val l2f = 0x89
+ final val l2d = 0x8a
+ final val f2i = 0x8b
+ final val f2l = 0x8c
+ final val f2d = 0x8d
+ final val d2i = 0x8e
+ final val d2l = 0x8f
+ final val d2f = 0x90
+ final val i2b = 0x91
+ final val i2c = 0x92
+ final val i2s = 0x93
+
+ final val lcmp = 0x94
+ final val fcmpl = 0x95
+ final val fcmpg = 0x96
+ final val dcmpl = 0x97
+ final val dcmpg = 0x98
+
+ final val ifeq = 0x99
+ final val ifne = 0x9a
+ final val iflt = 0x9b
+ final val ifge = 0x9c
+ final val ifgt = 0x9d
+ final val ifle = 0x9e
+ final val if_icmpeq = 0x9f
+ final val if_icmpne = 0xa0
+ final val if_icmplt = 0xa1
+ final val if_icmpge = 0xa2
+ final val if_icmpgt = 0xa3
+ final val if_icmple = 0xa4
+ final val if_acmpeq = 0xa5
+ final val if_acmpne = 0xa6
+ final val goto = 0xa7
+ final val jsr = 0xa8
+ final val ret = 0xa9
+ final val tableswitch = 0xaa
+ final val lookupswitch = 0xab
+ final val ireturn = 0xac
+ final val lreturn = 0xad
+ final val freturn = 0xae
+ final val dreturn = 0xaf
+ final val areturn = 0xb0
+ final val return_ = 0xb1
+
+ final val getstatic = 0xb2
+ final val putstatic = 0xb3
+ final val getfield = 0xb4
+ final val putfield = 0xb5
+
+ final val invokevirtual = 0xb6
+ final val invokespecial = 0xb7
+ final val invokestatic = 0xb8
+ final val invokeinterface = 0xb9
+ final val xxxunusedxxxx = 0xba
+
+ final val new_ = 0xbb
+ final val newarray = 0xbc
+ final val anewarray = 0xbd
+ final val arraylength = 0xbe
+ final val athrow = 0xbf
+ final val checkcast = 0xc0
+ final val instanceof = 0xc1
+ final val monitorenter = 0xc2
+ final val monitorexit = 0xc3
+ final val wide = 0xc4
+ final val multianewarray = 0xc5
+ final val ifnull = 0xc6
+ final val ifnonnull = 0xc7
+ final val goto_w = 0xc8
+ final val jsr_w = 0xc9
+
+ // reserved opcodes
+ final val breakpoint = 0xca
+ final val impdep1 = 0xfe
+ final val impdep2 = 0xff
+}
diff --git a/src/compiler/scala/reflect/common/Constants.scala b/src/compiler/scala/reflect/common/Constants.scala
new file mode 100644
index 0000000000..6e96dae3e6
--- /dev/null
+++ b/src/compiler/scala/reflect/common/Constants.scala
@@ -0,0 +1,238 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+import java.lang.Integer.toOctalString
+import annotation.switch
+
+trait Constants {
+ self: SymbolTable =>
+
+ import definitions._
+
+ final val NoTag = 0
+ final val UnitTag = 1
+ final val BooleanTag = 2
+ final val ByteTag = 3
+ final val ShortTag = 4
+ final val CharTag = 5
+ final val IntTag = 6
+ final val LongTag = 7
+ final val FloatTag = 8
+ final val DoubleTag = 9
+ final val StringTag = 10
+ final val NullTag = 11
+ final val ClassTag = 12
+ // For supporting java enumerations inside java annotations (see ClassfileParser)
+ final val EnumTag = 13
+
+ case class Constant(value: Any) {
+ val tag: Int = value match {
+ case null => NullTag
+ case x: Unit => UnitTag
+ case x: Boolean => BooleanTag
+ case x: Byte => ByteTag
+ case x: Short => ShortTag
+ case x: Int => IntTag
+ case x: Long => LongTag
+ case x: Float => FloatTag
+ case x: Double => DoubleTag
+ case x: String => StringTag
+ case x: Char => CharTag
+ case x: Type => ClassTag
+ case x: Symbol => EnumTag
+ case _ => throw new Error("bad constant value: " + value)
+ }
+
+ def isByteRange: Boolean = isIntRange && Byte.MinValue <= intValue && intValue <= Byte.MaxValue
+ def isShortRange: Boolean = isIntRange && Short.MinValue <= intValue && intValue <= Short.MaxValue
+ def isCharRange: Boolean = isIntRange && Char.MinValue <= intValue && intValue <= Char.MaxValue
+ def isIntRange: Boolean = ByteTag <= tag && tag <= IntTag
+ def isLongRange: Boolean = ByteTag <= tag && tag <= LongTag
+ def isFloatRange: Boolean = ByteTag <= tag && tag <= FloatTag
+ def isNumeric: Boolean = ByteTag <= tag && tag <= DoubleTag
+
+ def tpe: Type = tag match {
+ case UnitTag => UnitClass.tpe
+ case BooleanTag => BooleanClass.tpe
+ case ByteTag => ByteClass.tpe
+ case ShortTag => ShortClass.tpe
+ case CharTag => CharClass.tpe
+ case IntTag => IntClass.tpe
+ case LongTag => LongClass.tpe
+ case FloatTag => FloatClass.tpe
+ case DoubleTag => DoubleClass.tpe
+ case StringTag => StringClass.tpe
+ case NullTag => NullClass.tpe
+ case ClassTag => ClassType(value.asInstanceOf[Type])
+ case EnumTag =>
+ // given (in java): "class A { enum E { VAL1 } }"
+ // - symbolValue: the symbol of the actual enumeration value (VAL1)
+ // - .owner: the ModuleClasSymbol of the enumeration (object E)
+ // - .linkedClassOfClass: the ClassSymbol of the enumeration (class E)
+ symbolValue.owner.linkedClassOfClass.tpe
+ }
+
+ /** We need the equals method to take account of tags as well as values.
+ */
+ override def equals(other: Any): Boolean = other match {
+ case that: Constant =>
+ this.tag == that.tag &&
+ (this.value == that.value || this.isNaN && that.isNaN)
+ case _ => false
+ }
+
+ def isNaN = value match {
+ case f: Float => f.isNaN
+ case d: Double => d.isNaN
+ case _ => false
+ }
+
+ def booleanValue: Boolean =
+ if (tag == BooleanTag) value.asInstanceOf[Boolean]
+ else throw new Error("value " + value + " is not a boolean");
+
+ def byteValue: Byte = tag match {
+ case ByteTag => value.asInstanceOf[Byte]
+ case ShortTag => value.asInstanceOf[Short].toByte
+ case CharTag => value.asInstanceOf[Char].toByte
+ case IntTag => value.asInstanceOf[Int].toByte
+ case LongTag => value.asInstanceOf[Long].toByte
+ case FloatTag => value.asInstanceOf[Float].toByte
+ case DoubleTag => value.asInstanceOf[Double].toByte
+ case _ => throw new Error("value " + value + " is not a Byte")
+ }
+
+ def shortValue: Short = tag match {
+ case ByteTag => value.asInstanceOf[Byte].toShort
+ case ShortTag => value.asInstanceOf[Short]
+ case CharTag => value.asInstanceOf[Char].toShort
+ case IntTag => value.asInstanceOf[Int].toShort
+ case LongTag => value.asInstanceOf[Long].toShort
+ case FloatTag => value.asInstanceOf[Float].toShort
+ case DoubleTag => value.asInstanceOf[Double].toShort
+ case _ => throw new Error("value " + value + " is not a Short")
+ }
+
+ def charValue: Char = tag match {
+ case ByteTag => value.asInstanceOf[Byte].toChar
+ case ShortTag => value.asInstanceOf[Short].toChar
+ case CharTag => value.asInstanceOf[Char]
+ case IntTag => value.asInstanceOf[Int].toChar
+ case LongTag => value.asInstanceOf[Long].toChar
+ case FloatTag => value.asInstanceOf[Float].toChar
+ case DoubleTag => value.asInstanceOf[Double].toChar
+ case _ => throw new Error("value " + value + " is not a Char")
+ }
+
+ def intValue: Int = tag match {
+ case ByteTag => value.asInstanceOf[Byte].toInt
+ case ShortTag => value.asInstanceOf[Short].toInt
+ case CharTag => value.asInstanceOf[Char].toInt
+ case IntTag => value.asInstanceOf[Int]
+ case LongTag => value.asInstanceOf[Long].toInt
+ case FloatTag => value.asInstanceOf[Float].toInt
+ case DoubleTag => value.asInstanceOf[Double].toInt
+ case _ => throw new Error("value " + value + " is not an Int")
+ }
+
+ def longValue: Long = tag match {
+ case ByteTag => value.asInstanceOf[Byte].toLong
+ case ShortTag => value.asInstanceOf[Short].toLong
+ case CharTag => value.asInstanceOf[Char].toLong
+ case IntTag => value.asInstanceOf[Int].toLong
+ case LongTag => value.asInstanceOf[Long]
+ case FloatTag => value.asInstanceOf[Float].toLong
+ case DoubleTag => value.asInstanceOf[Double].toLong
+ case _ => throw new Error("value " + value + " is not a Long")
+ }
+
+ def floatValue: Float = tag match {
+ case ByteTag => value.asInstanceOf[Byte].toFloat
+ case ShortTag => value.asInstanceOf[Short].toFloat
+ case CharTag => value.asInstanceOf[Char].toFloat
+ case IntTag => value.asInstanceOf[Int].toFloat
+ case LongTag => value.asInstanceOf[Long].toFloat
+ case FloatTag => value.asInstanceOf[Float]
+ case DoubleTag => value.asInstanceOf[Double].toFloat
+ case _ => throw new Error("value " + value + " is not a Float")
+ }
+
+ def doubleValue: Double = tag match {
+ case ByteTag => value.asInstanceOf[Byte].toDouble
+ case ShortTag => value.asInstanceOf[Short].toDouble
+ case CharTag => value.asInstanceOf[Char].toDouble
+ case IntTag => value.asInstanceOf[Int].toDouble
+ case LongTag => value.asInstanceOf[Long].toDouble
+ case FloatTag => value.asInstanceOf[Float].toDouble
+ case DoubleTag => value.asInstanceOf[Double]
+ case _ => throw new Error("value " + value + " is not a Double")
+ }
+
+ /** Convert constant value to conform to given type.
+ */
+ def convertTo(pt: Type): Constant = {
+ val target = pt.typeSymbol
+ if (target == tpe.typeSymbol)
+ this
+ else if (target == ByteClass && isByteRange)
+ Constant(byteValue)
+ else if (target == ShortClass && isShortRange)
+ Constant(shortValue)
+ else if (target == CharClass && isCharRange)
+ Constant(charValue)
+ else if (target == IntClass && isIntRange)
+ Constant(intValue)
+ else if (target == LongClass && isLongRange)
+ Constant(longValue)
+ else if (target == FloatClass && isFloatRange)
+ Constant(floatValue)
+ else if (target == DoubleClass && isNumeric)
+ Constant(doubleValue)
+ else
+ null
+ }
+
+ def stringValue: String =
+ if (value == null) "null"
+ else if (tag == ClassTag) signature(typeValue)
+ else value.toString()
+
+ @switch def escapedChar(ch: Char): String = ch match {
+ case '\b' => "\\b"
+ case '\t' => "\\t"
+ case '\n' => "\\n"
+ case '\f' => "\\f"
+ case '\r' => "\\r"
+ case '"' => "\\\""
+ case '\'' => "\\\'"
+ case '\\' => "\\\\"
+ case _ => String.valueOf(ch)
+ }
+
+ def escapedStringValue: String = {
+ def escape(text: String): String = {
+ text map { ch =>
+ if (ch.isControl) "\\0" + toOctalString(ch)
+ else escapedChar(ch)
+ } mkString ""
+ }
+ tag match {
+ case NullTag => "null"
+ case StringTag => "\"" + escape(stringValue) + "\""
+ case ClassTag => "classOf[" + signature(typeValue) + "]"
+ case CharTag => escape("'" + escapedChar(charValue) + "'")
+ case LongTag => longValue.toString() + "L"
+ case _ => String.valueOf(value)
+ }
+ }
+ def typeValue: Type = value.asInstanceOf[Type]
+ def symbolValue: Symbol = value.asInstanceOf[Symbol]
+
+ override def hashCode: Int = value.## * 41 + 17
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/reflect/common/Definitions.scala
index 6b419c629d..f2c4fc844e 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/reflect/common/Definitions.scala
@@ -3,17 +3,15 @@
* @author Martin Odersky
*/
-package scala.tools.nsc
-package symtab
+package scala.reflect
+package common
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.{ HashMap }
-import scala.tools.nsc.util.NoPosition
import Flags._
import PartialFunction._
-import classfile.ClassfileConstants
-trait Definitions extends reflect.generic.StandardDefinitions {
+trait Definitions /*extends reflect.generic.StandardDefinitions*/ {
self: SymbolTable =>
// the scala value classes
@@ -117,7 +115,7 @@ trait Definitions extends reflect.generic.StandardDefinitions {
)
}
- object definitions extends AbsDefinitions with ValueClassDefinitions {
+ object definitions extends ValueClassDefinitions {
private var isInitialized = false
def isDefinitionsInitialized = isInitialized
diff --git a/src/compiler/scala/reflect/common/Flags.scala b/src/compiler/scala/reflect/common/Flags.scala
index 756ea3077b..8cdecd0da1 100644
--- a/src/compiler/scala/reflect/common/Flags.scala
+++ b/src/compiler/scala/reflect/common/Flags.scala
@@ -250,6 +250,8 @@ class Flags extends ModifierFlags {
private final val PKL_MASK = 0x00000FFF
+ final val PickledFlags: Long = 0xFFFFFFFFL
+
private def rawPickledCorrespondence = Array(
(IMPLICIT, IMPLICIT_PKL),
(FINAL, FINAL_PKL),
diff --git a/src/compiler/scala/reflect/common/HasFlags.scala b/src/compiler/scala/reflect/common/HasFlags.scala
new file mode 100644
index 0000000000..cbdd20b122
--- /dev/null
+++ b/src/compiler/scala/reflect/common/HasFlags.scala
@@ -0,0 +1,231 @@
+package scala.reflect
+package common
+
+/** ISSUE #1: Flag names vs. Test method names
+ *
+ * The following methods from Symbol have a name of
+ * the form isFoo where FOO is the name of a flag, but where the method
+ * body tests for more than whether the flag is set.
+ *
+ * There are two possibilities with such methods. Either the extra
+ * tests are strictly to partition among overloaded flags (which is
+ * the case we can live with in the short term, if each such flag's
+ * partitioning assumptions are documented) or they aren't.
+ *
+ * The second case implies that "x hasFlag FOO" and "x.isFoo" have
+ * different semantics, and this we can't live with, because even if
+ * we're smart enough to avoid being tripped up by that, the next guy isn't.
+ *
+ * No extreme measures necessary, only renaming isFoo to something
+ * which hews more closely to its implementation. (Or renaming the flag.)
+ *
+ // Defined in the compiler Symbol
+ //
+ final def isLabel = isMethod && !hasAccessorFlag && hasFlag(LABEL)
+ final def isLocal: Boolean = owner.isTerm
+ final def isModuleVar: Boolean = isVariable && hasFlag(MODULEVAR)
+ final def isStable =
+ isTerm &&
+ !hasTraitFlag &&
+ (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) &&
+ !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass))
+ final def isStatic: Boolean =
+ hasFlag(STATIC) || isRoot || owner.isStaticOwner
+ override final def isTrait: Boolean =
+ isClass && hasFlag(TRAIT | notDEFERRED) // A virtual class becomes a trait (part of DEVIRTUALIZE)
+
+ // Defined in the library Symbol
+ //
+ def isTrait: Boolean = isClass && hasFlag(TRAIT) // refined later for virtual classes.
+ final def isContravariant = isType && hasFlag(CONTRAVARIANT)
+ final def isCovariant = isType && hasFlag(COVARIANT)
+ final def isMethod = isTerm && hasFlag(METHOD)
+ final def isModule = isTerm && hasFlag(MODULE)
+ final def isPackage = isModule && hasFlag(PACKAGE)
+ *
+ */
+
+/** ISSUE #2: Implicit flag relationships must be made explicit.
+ *
+ * For instance, every time the MODULE flag is set, the FINAL flag is
+ * set along with it:
+ *
+ .setFlag(FINAL | MODULE | PACKAGE | JAVA)
+ .setFlag(FINAL | MODULE | PACKAGE | JAVA).setInfo(rootLoader)
+ new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
+ new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
+ val m = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
+ setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL)
+ sourceModule.flags = MODULE | FINAL
+
+ * However the same is not true of when the MODULE flag is cleared:
+
+ sym.resetFlag(MODULE)
+ .setFlag(sym.flags | STABLE).resetFlag(MODULE)
+ sym.resetFlag(MODULE | FINAL | CASE)
+
+ * It's not relevant whether this example poses any issues: we must
+ * not tolerate these uncertainties. If the flags are to move together
+ * then both setting and clearing have to be encapsulated. If there
+ * is a useful and used distinction between the various permutations
+ * of on and off, then it must be documented. It's the only way!
+ */
+
+import Flags._
+
+/** Common code utilized by Modifiers (which carry the flags associated
+ * with Trees) and Symbol.
+ */
+trait HasFlags {
+ type FlagsType
+ type AccessBoundaryType
+ type AnnotationType
+
+ /** Though both Symbol and Modifiers widen this method to public, it's
+ * defined protected here to give us the option in the future to route
+ * flag methods through accessors and disallow raw flag manipulation.
+ * And after that, perhaps, on some magical day: a typesafe enumeration.
+ */
+ protected def flags: FlagsType
+
+ /** The printable representation of this entity's flags and access boundary,
+ * restricted to flags in the given mask.
+ */
+ def hasFlagsToString(mask: FlagsType): String
+
+ /** Access level encoding: there are three scala flags (PRIVATE, PROTECTED,
+ * and LOCAL) which combine with value privateWithin (the "foo" in private[foo])
+ * to define from where an entity can be accessed. The meanings are as follows:
+ *
+ * PRIVATE access restricted to class only.
+ * PROTECTED access restricted to class and subclasses only.
+ * LOCAL can only be set in conjunction with PRIVATE or PROTECTED.
+ * Further restricts access to the same object instance.
+ *
+ * In addition, privateWithin can be used to set a visibility barrier.
+ * When set, everything contained in the named enclosing package or class
+ * has access. It is incompatible with PRIVATE or LOCAL, but is additive
+ * with PROTECTED (i.e. if either the flags or privateWithin allow access,
+ * then it is allowed.)
+ *
+ * The java access levels translate as follows:
+ *
+ * java private: hasFlag(PRIVATE) && !hasAccessBoundary
+ * java package: !hasFlag(PRIVATE | PROTECTED) && (privateWithin == enclosing package)
+ * java protected: hasFlag(PROTECTED) && (privateWithin == enclosing package)
+ * java public: !hasFlag(PRIVATE | PROTECTED) && !hasAccessBoundary
+ */
+ def privateWithin: AccessBoundaryType
+
+ /** A list of annotations attached to this entity.
+ */
+ def annotations: List[AnnotationType]
+
+ /** Whether this entity has a "privateWithin" visibility barrier attached.
+ */
+ def hasAccessBoundary: Boolean
+
+ /** Whether this entity has ANY of the flags in the given mask.
+ */
+ def hasFlag(flag: Long): Boolean
+
+ /** Whether this entity has ALL of the flags in the given mask.
+ */
+ def hasAllFlags(mask: Long): Boolean
+
+ /** Whether this entity has NONE of the flags in the given mask.
+ */
+ def hasNoFlags(mask: Long): Boolean = !hasFlag(mask)
+
+ // Tests which come through cleanly: both Symbol and Modifiers use these
+ // identically, testing for a single flag.
+ def isCase = hasFlag(CASE )
+ def isFinal = hasFlag(FINAL )
+ def isImplicit = hasFlag(IMPLICIT )
+ def isLazy = hasFlag(LAZY )
+ def isMutable = hasFlag(MUTABLE ) // in Modifiers, formerly isVariable
+ def isOverride = hasFlag(OVERRIDE )
+ def isPrivate = hasFlag(PRIVATE )
+ def isProtected = hasFlag(PROTECTED)
+ def isSynthetic = hasFlag(SYNTHETIC)
+ def isInterface = hasFlag(INTERFACE)
+
+ // Newly introduced based on having a reasonably obvious clean translation.
+ def isPrivateLocal = hasAllFlags(PRIVATE | LOCAL)
+ def isProtectedLocal = hasAllFlags(PROTECTED | LOCAL)
+ def isParamAccessor = hasFlag(PARAMACCESSOR)
+ def isCaseAccessor = hasFlag(CASEACCESSOR)
+ def isSuperAccessor = hasFlag(SUPERACCESSOR)
+ def isLifted = hasFlag(LIFTED)
+
+ // Formerly the Modifiers impl did not include the access boundary check,
+ // which must have been a bug.
+ def isPublic = hasNoFlags(PRIVATE | PROTECTED) && !hasAccessBoundary
+
+ // Renamed the Modifiers impl from isArgument.
+ def isParameter = hasFlag(PARAM)
+
+ // Removed isClass qualification since the flag isn't overloaded and
+ // sym.isClass is enforced in Namers#validate.
+ def isSealed = hasFlag(SEALED)
+
+ // Removed !isClass qualification since the flag isn't overloaded.
+ def isDeferred = hasFlag(DEFERRED )
+
+ // Dropped isTerm condition because flag isn't overloaded.
+ def isAbstractOverride = hasFlag(ABSOVERRIDE)
+
+ def isDefaultInit = hasFlag(DEFAULTINIT)
+
+ // Disambiguating: DEFAULTPARAM, TRAIT
+ def hasDefault = hasAllFlags(DEFAULTPARAM | PARAM)
+ def isTrait = hasFlag(TRAIT) && !hasFlag(PARAM)
+ def hasTraitFlag = hasFlag(TRAIT)
+ def hasDefaultFlag = hasFlag(DEFAULTPARAM)
+
+ // Straightforwardly named accessors already being used differently.
+ // These names are most likely temporary.
+ def hasAbstractFlag = hasFlag(ABSTRACT)
+ def hasAccessorFlag = hasFlag(ACCESSOR)
+ def hasLocalFlag = hasFlag(LOCAL)
+ def hasModuleFlag = hasFlag(MODULE)
+ def hasPackageFlag = hasFlag(PACKAGE)
+ def hasPreSuperFlag = hasFlag(PRESUPER)
+ def hasStableFlag = hasFlag(STABLE)
+ def hasStaticFlag = hasFlag(STATIC)
+
+ // Disambiguating: BYNAMEPARAM, CAPTURED, COVARIANT.
+ def isByNameParam = hasAllFlags(BYNAMEPARAM | PARAM)
+ // Nope, these aren't going to fly:
+ // def isCapturedVariable = hasAllFlags(CAPTURED | MUTABLE)
+ // def isCovariant = hasFlag(COVARIANT) && hasNoFlags(PARAM | MUTABLE)
+
+ // Disambiguating: LABEL, CONTRAVARIANT, INCONSTRUCTOR
+ def isLabel = hasAllFlags(LABEL | METHOD) && !hasAccessorFlag
+ // Cannot effectively disambiguate the others at this level.
+ def hasContravariantFlag = hasFlag(CONTRAVARIANT)
+ def hasInConstructorFlag = hasFlag(INCONSTRUCTOR)
+
+ // Name
+ def isJavaDefined = hasFlag(JAVA)
+
+ // Keeping some potentially ambiguous names around so as not to break
+ // the rest of the world
+ @deprecated("", "2.9.0")
+ def isAbstract = hasFlag(ABSTRACT)
+ // Problematic:
+ // ABSTRACT and DEFERRED too easy to confuse, and
+ // ABSTRACT + OVERRIDE ==> ABSOVERRIDE adds to it.
+ //
+ // final def isAbstractClass = isClass && hasFlag(ABSTRACT)
+ // def isAbstractType = false // to be overridden
+
+ // Question:
+ // Which name? All other flags are isFlag so it's probably a mistake to
+ // vary from that, but isAccessor does sound like it includes the other
+ // *ACCESSOR flags. Perhaps something like isSimpleAccessor.
+ //
+ // def isAccessor = hasFlag(ACCESSOR )
+ // final def isGetterOrSetter = hasAccessorFlag
+}
+
diff --git a/src/compiler/scala/reflect/common/InfoTransformers.scala b/src/compiler/scala/reflect/common/InfoTransformers.scala
new file mode 100644
index 0000000000..12fd57caee
--- /dev/null
+++ b/src/compiler/scala/reflect/common/InfoTransformers.scala
@@ -0,0 +1,47 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+trait InfoTransformers {
+ self: SymbolTable =>
+
+ abstract class InfoTransformer {
+ var prev: InfoTransformer = this
+ var next: InfoTransformer = this
+
+ val pid: Phase#Id
+ val changesBaseClasses: Boolean
+ def transform(sym: Symbol, tpe: Type): Type
+
+ def insert(that: InfoTransformer) {
+ assert(this.pid != that.pid)
+ if (that.pid < this.pid) {
+ prev insert that
+ } else if (next.pid <= that.pid && next.pid != NoPhase.id) {
+ next insert that
+ } else {
+ that.next = next
+ that.prev = this
+ next.prev = that
+ this.next = that
+ }
+ }
+
+ /** The InfoTransformer whose (pid == from).
+ * If no such exists, the InfoTransformer with the next
+ * higher pid.
+ */
+ def nextFrom(from: Phase#Id): InfoTransformer =
+ if (from == this.pid) this
+ else if (from < this.pid)
+ if (prev.pid < from) this
+ else prev.nextFrom(from);
+ else if (next.pid == NoPhase.id) next
+ else next.nextFrom(from)
+ }
+}
+
diff --git a/src/compiler/scala/reflect/common/NameManglers.scala b/src/compiler/scala/reflect/common/NameManglers.scala
new file mode 100644
index 0000000000..2f603d36ed
--- /dev/null
+++ b/src/compiler/scala/reflect/common/NameManglers.scala
@@ -0,0 +1,172 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+import java.security.MessageDigest
+import scala.io.Codec
+import Chars.isOperatorPart
+
+/** A trait to encapsulate name mangling. It's intended for the
+ * values and methods involved in assembling names out of other names,
+ * and not for simple synthetically named locals.
+ */
+trait NameManglers {
+ self: SymbolTable =>
+
+ trait NameManglingCommon {
+ self: CommonNames =>
+
+ def flattenedName(segments: Name*): NameType = compactedString(segments mkString "$")
+
+ /**
+ * COMPACTIFY
+ *
+ * The hashed name has the form (prefix + marker + md5 + marker + suffix), where
+ * - prefix/suffix.length = MaxNameLength / 4
+ * - md5.length = 32
+ *
+ * We obtain the formula:
+ *
+ * FileNameLength = 2*(MaxNameLength / 4) + 2.marker.length + 32 + 6
+ *
+ * (+6 for ".class"). MaxNameLength can therefore be computed as follows:
+ */
+ private final val marker = "$$$$"
+ private final val MaxNameLength = math.min(
+ settings.maxClassfileName.value - 6,
+ 2 * (settings.maxClassfileName.value - 6 - 2*marker.length - 32)
+ )
+ private lazy val md5 = MessageDigest.getInstance("MD5")
+ private def toMD5(s: String, edge: Int) = {
+ val prefix = s take edge
+ val suffix = s takeRight edge
+
+ val cs = s.toArray
+ val bytes = Codec toUTF8 cs
+ md5 update bytes
+ val md5chars = md5.digest() map (b => (b & 0xFF).toHexString) mkString
+
+ prefix + marker + md5chars + marker + suffix
+ }
+ private def compactedString(s: String) =
+ if (s.length <= MaxNameLength) s
+ else toMD5(s, MaxNameLength / 4)
+ }
+
+ trait TypeNameMangling extends NameManglingCommon {
+ self: tpnme.type =>
+
+ }
+
+ trait TermNameMangling extends NameManglingCommon {
+ self: nme.type =>
+
+ val IMPL_CLASS_SUFFIX = "$class"
+ val SINGLETON_SUFFIX = ".type"
+ val LOCALDUMMY_PREFIX = "<local " // owner of local blocks
+ val PROTECTED_PREFIX = "protected$"
+ val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set"
+ val SELECTOR_DUMMY = "<unapply-selector>"
+ val SETTER_SUFFIX = encode("_=")
+ val SUPER_PREFIX_STRING = "super$"
+ val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$"
+
+ def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR
+ def isExceptionResultName(name: Name) = name startsWith EXCEPTION_RESULT_PREFIX
+ /** !!! Foo$class$1 is an implClassName, I think. */
+ def isImplClassName(name: Name) = name endsWith IMPL_CLASS_SUFFIX
+ def isLocalDummyName(name: Name) = name startsWith LOCALDUMMY_PREFIX
+ def isLocalName(name: Name) = name endsWith LOCAL_SUFFIX_STRING
+ def isLoopHeaderLabel(name: Name) = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX)
+ def isProtectedAccessorName(name: Name) = name startsWith PROTECTED_PREFIX
+ def isReplWrapperName(name: Name) = name containsName INTERPRETER_IMPORT_WRAPPER
+ def isSetterName(name: Name) = name endsWith SETTER_SUFFIX
+ def isTraitSetterName(name: Name) = isSetterName(name) && (name containsName TRAIT_SETTER_SEPARATOR_STRING)
+ def isSingletonName(name: Name) = name endsWith SINGLETON_SUFFIX
+
+ def isOpAssignmentName(name: Name) = name match {
+ case raw.NE | raw.LE | raw.GE | EMPTY => false
+ case _ =>
+ name.endChar == '=' && name.startChar != '=' && isOperatorPart(name.startChar)
+ }
+
+ /** The expanded setter name of `name' relative to this class `base`
+ */
+ def expandedSetterName(name: TermName, base: Symbol): TermName =
+ expandedName(name, base, separator = TRAIT_SETTER_SEPARATOR_STRING)
+
+ /** If `name' is an expandedName name, the original name.
+ * Otherwise `name' itself.
+ */
+ def originalName(name: Name): Name = {
+ var i = name.length
+ while (i >= 2 && !(name(i - 1) == '$' && name(i - 2) == '$')) i -= 1
+ if (i >= 2) {
+ while (i >= 3 && name(i - 3) == '$') i -= 1
+ name.subName(i, name.length)
+ } else name
+ }
+
+ /** Return the original name and the types on which this name
+ * is specialized. For example,
+ * {{{
+ * splitSpecializedName("foo$mIcD$sp") == ('foo', "I", "D")
+ * }}}
+ * `foo$mIcD$sp` is the name of a method specialized on two type
+ * parameters, the first one belonging to the method itself, on Int,
+ * and another one belonging to the enclosing class, on Double.
+ */
+ def splitSpecializedName(name: Name): (Name, String, String) =
+ if (name.endsWith("$sp")) {
+ val name1 = name stripEnd "$sp"
+ val idxC = name1 lastIndexOf 'c'
+ val idxM = name1 lastIndexOf 'm'
+
+ (name1.subName(0, idxM - 1),
+ name1.subName(idxC + 1, name1.length).toString,
+ name1.subName(idxM + 1, idxC).toString)
+ } else
+ (name, "", "")
+
+ def getterName(name: TermName): TermName = if (isLocalName(name)) localToGetter(name) else name
+ def getterToLocal(name: TermName): TermName = name.toTermName append LOCAL_SUFFIX_STRING
+ def getterToSetter(name: TermName): TermName = name.toTermName append SETTER_SUFFIX
+ def localToGetter(name: TermName): TermName = name stripEnd LOCAL_SUFFIX_STRING toTermName
+
+ def setterToGetter(name: TermName): TermName = {
+ val p = name.pos(TRAIT_SETTER_SEPARATOR_STRING)
+ if (p < name.length)
+ setterToGetter(name.subName(p + TRAIT_SETTER_SEPARATOR_STRING.length, name.length))
+ else
+ name stripEnd SETTER_SUFFIX toTermName
+ }
+
+ def defaultGetterName(name: Name, pos: Int): TermName = {
+ val prefix = if (isConstructorName(name)) "init" else name
+ newTermName(prefix + DEFAULT_GETTER_STRING + pos)
+ }
+ def defaultGetterToMethod(name: Name): TermName = {
+ val p = name.pos(DEFAULT_GETTER_STRING)
+ if (p < name.length) name.subName(0, p)
+ else name
+ }
+
+ def dropSingletonName(name: Name): TypeName = name stripEnd SINGLETON_SUFFIX toTypeName
+ def singletonName(name: Name): TypeName = name append SINGLETON_SUFFIX toTypeName
+ def implClassName(name: Name): TypeName = name append IMPL_CLASS_SUFFIX toTypeName
+ def interfaceName(implname: Name): TypeName = implname stripEnd IMPL_CLASS_SUFFIX toTypeName
+ def localDummyName(clazz: Symbol): TermName = newTermName(LOCALDUMMY_PREFIX + clazz.name + ">")
+ def productAccessorName(i: Int): TermName = newTermName("_" + i)
+ def superName(name: Name): TermName = newTermName(SUPER_PREFIX_STRING + name)
+
+ /** The name of an accessor for protected symbols. */
+ def protName(name: Name): TermName = newTermName(PROTECTED_PREFIX + name)
+
+ /** The name of a setter for protected symbols. Used for inherited Java fields. */
+ def protSetterName(name: Name): TermName = newTermName(PROTECTED_SET_PREFIX + name)
+ }
+}
diff --git a/src/compiler/scala/reflect/common/Names.scala b/src/compiler/scala/reflect/common/Names.scala
new file mode 100644
index 0000000000..4122d7ba2d
--- /dev/null
+++ b/src/compiler/scala/reflect/common/Names.scala
@@ -0,0 +1,434 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+import scala.reflect.NameTransformer
+import scala.io.Codec
+import java.security.MessageDigest
+
+/** The class Names ...
+ *
+ * @author Martin Odersky
+ * @version 1.0, 05/02/2005
+ */
+trait Names /*extends reflect.generic.Names*/ {
+
+// Operations -------------------------------------------------------------
+
+ private final val HASH_SIZE = 0x8000
+ private final val HASH_MASK = 0x7FFF
+ private final val NAME_SIZE = 0x20000
+
+ final val nameDebug = false
+
+ /** memory to store all names sequentially
+ */
+ var chrs: Array[Char] = new Array[Char](NAME_SIZE)
+ private var nc = 0
+
+ /** hashtable for finding term names quickly
+ */
+ private val termHashtable = new Array[TermName](HASH_SIZE)
+
+ /** hashtable for finding type names quickly
+ */
+ private val typeHashtable = new Array[TypeName](HASH_SIZE)
+
+ /** the hashcode of a name
+ */
+ private def hashValue(cs: Array[Char], offset: Int, len: Int): Int =
+ if (len > 0)
+ (len * (41 * 41 * 41) +
+ cs(offset) * (41 * 41) +
+ cs(offset + len - 1) * 41 +
+ cs(offset + (len >> 1)))
+ else 0;
+
+ /** Is (the ASCII representation of) name at given index equal to
+ * cs[offset..offset+len-1]?
+ */
+ private def equals(index: Int, cs: Array[Char], offset: Int, len: Int): Boolean = {
+ var i = 0
+ while ((i < len) && (chrs(index + i) == cs(offset + i)))
+ i += 1;
+ i == len
+ }
+
+ /** enter characters into chrs array
+ */
+ private def enterChars(cs: Array[Char], offset: Int, len: Int) {
+ var i = 0
+ while (i < len) {
+ if (nc + i == chrs.length) {
+ val newchrs = new Array[Char](chrs.length * 2)
+ compat.Platform.arraycopy(chrs, 0, newchrs, 0, chrs.length)
+ chrs = newchrs
+ }
+ chrs(nc + i) = cs(offset + i)
+ i += 1
+ }
+ if (len == 0) nc += 1
+ else nc = nc + len
+ }
+
+ /** Create a term name from the characters in cs[offset..offset+len-1].
+ */
+ def newTermName(cs: Array[Char], offset: Int, len: Int): TermName = {
+ val h = hashValue(cs, offset, len) & HASH_MASK
+ var n = termHashtable(h)
+ while ((n ne null) && (n.length != len || !equals(n.start, cs, offset, len)))
+ n = n.next;
+ if (n eq null) {
+ n = new TermName(nc, len, h)
+ enterChars(cs, offset, len)
+ }
+ n
+ }
+
+ /** create a term name from string
+ */
+ def newTermName(s: String): TermName =
+ newTermName(s.toCharArray(), 0, s.length())
+
+ /** Create a term name from the UTF8 encoded bytes in bs[offset..offset+len-1].
+ */
+ def newTermName(bs: Array[Byte], offset: Int, len: Int): TermName =
+ newTermName(Codec fromUTF8 bs.slice(offset, offset + len) mkString)
+
+ /** Create a type name from the characters in cs[offset..offset+len-1].
+ */
+ def newTypeName(cs: Array[Char], offset: Int, len: Int): TypeName =
+ newTermName(cs, offset, len).toTypeName
+
+ /** Create a type name from string
+ */
+ def newTypeName(s: String): TypeName =
+ newTermName(s).toTypeName
+
+ /** Create a type name from the UTF8 encoded bytes in bs[offset..offset+len-1].
+ */
+ def newTypeName(bs: Array[Byte], offset: Int, len: Int): TypeName =
+ newTermName(bs, offset, len).toTypeName
+
+ def mkTermName(name: Name): TermName = name.toTermName
+ def mkTypeName(name: Name): TypeName = name.toTypeName
+ def isTermName(name: Name): Boolean = name.isTermName
+ def isTypeName(name: Name): Boolean = name.isTypeName
+
+ def nameChars: Array[Char] = chrs
+ @deprecated("", "2.9.0") def view(s: String): TermName = newTermName(s)
+
+ /** An implicit conversion from names to term names
+ */
+ implicit def promoteTermNamesAsNecessary(name: Name): TermName = mkTermName(name)
+
+
+// Classes ----------------------------------------------------------------------
+
+ /** The name class. */
+ sealed abstract class Name(protected val index: Int, protected val len: Int) extends Function1[Int, Char] {
+ /** Index into name table */
+ def start: Int = index
+
+ /** next name in the same hash bucket
+ */
+ def next: Name
+
+ /** return the length of this name
+ */
+ final def length: Int = len
+ final def isEmpty = length == 0
+ final def nonEmpty = !isEmpty
+
+ def isTermName: Boolean
+ def isTypeName: Boolean
+ def toTermName: TermName
+ def toTypeName: TypeName
+ def companionName: Name
+ def bothNames: List[Name] = List(toTermName, toTypeName)
+
+ /** Copy bytes of this name to buffer cs, starting at position `offset`.
+ */
+ final def copyChars(cs: Array[Char], offset: Int) =
+ compat.Platform.arraycopy(chrs, index, cs, offset, len)
+
+ /** return the ascii representation of this name
+ */
+ final def toChars: Array[Char] = {
+ val cs = new Array[Char](len)
+ copyChars(cs, 0)
+ cs
+ }
+
+ /** return the string representation of this name
+ */
+ final override def toString(): String = new String(chrs, index, len)
+ def debugString() = NameTransformer.decode(toString) + (if (isTypeName) "!" else "")
+
+ /** Write to UTF8 representation of this name to given character array.
+ * Start copying to index `to'. Return index of next free byte in array.
+ * Array must have enough remaining space for all bytes
+ * (i.e. maximally 3*length bytes).
+ */
+ final def copyUTF8(bs: Array[Byte], offset: Int): Int = {
+ val bytes = Codec toUTF8 chrs.slice(index, index + len)
+ compat.Platform.arraycopy(bytes, 0, bs, offset, bytes.length)
+ offset + bytes.length
+ }
+
+ /** return the hash value of this name
+ */
+ final override def hashCode(): Int = index
+
+ // Presently disabled.
+ // override def equals(other: Any) = paranoidEquals(other)
+ private def paranoidEquals(other: Any): Boolean = {
+ val cmp = this eq other.asInstanceOf[AnyRef]
+ if (cmp || !nameDebug)
+ return cmp
+
+ other match {
+ case x: String =>
+ Console.println("Compared " + debugString + " and String '" + x + "'")
+ case x: Name =>
+ if (this.isTermName != x.isTermName) {
+ val panic = this.toTermName == x.toTermName
+ Console.println("Compared '%s' and '%s', one term, one type.%s".format(this, x,
+ if (panic) " And they contain the same name string!"
+ else ""
+ ))
+ }
+ case _ =>
+ }
+ false
+ }
+
+ /** return the i'th Char of this name
+ */
+ final def apply(i: Int): Char = chrs(index + i)
+
+ /** return the index of first occurrence of char c in this name, length if not found */
+ final def pos(c: Char): Int = pos(c, 0)
+
+ /** return the index of first occurrence of char c in this name, length if not found */
+ final def pos(s: String): Int = pos(s, 0)
+
+ /** return the index of the first occurrence of character c in
+ * this name from start, length if not found.
+ *
+ * @param c the character
+ * @param start ...
+ * @return the index of the first occurrence of c
+ */
+ final def pos(c: Char, start: Int): Int = {
+ var i = start
+ while (i < len && chrs(index + i) != c) i += 1
+ i
+ }
+
+ /** return the index of the first occurrence of nonempty string s
+ * in this name from start, length if not found.
+ *
+ * @param s the string
+ * @param start ...
+ * @return the index of the first occurrence of s
+ */
+ final def pos(s: String, start: Int): Int = {
+ var i = pos(s.charAt(0), start)
+ while (i + s.length() <= len) {
+ var j = 1
+ while (s.charAt(j) == chrs(index + i + j)) {
+ j += 1
+ if (j == s.length()) return i
+ }
+ i = pos(s.charAt(0), i + 1)
+ }
+ len
+ }
+
+ /** return the index of last occurrence of char c in this
+ * name, -1 if not found.
+ *
+ * @param c the character
+ * @return the index of the last occurrence of c
+ */
+ final def lastPos(c: Char): Int = lastPos(c, len - 1)
+
+ final def lastPos(s: String): Int = lastPos(s, len - s.length)
+
+ /** return the index of the last occurrence of char c in this
+ * name from start, -1 if not found.
+ *
+ * @param c the character
+ * @param start ...
+ * @return the index of the last occurrence of c
+ */
+ final def lastPos(c: Char, start: Int): Int = {
+ var i = start
+ while (i >= 0 && chrs(index + i) != c) i -= 1
+ i
+ }
+
+ /** return the index of the last occurrence of string s in this
+ * name from start, -1 if not found.
+ *
+ * @param s the string
+ * @param start ...
+ * @return the index of the last occurrence of s
+ */
+ final def lastPos(s: String, start: Int): Int = {
+ var i = lastPos(s.charAt(0), start)
+ while (i >= 0) {
+ var j = 1;
+ while (s.charAt(j) == chrs(index + i + j)) {
+ j += 1
+ if (j == s.length()) return i;
+ }
+ i = lastPos(s.charAt(0), i - 1)
+ }
+ -s.length()
+ }
+
+ /** does this name start with prefix?
+ */
+ final def startsWith(prefix: Name): Boolean = startsWith(prefix, 0)
+
+ /** does this name start with prefix at given start index?
+ */
+ final def startsWith(prefix: Name, start: Int): Boolean = {
+ var i = 0
+ while (i < prefix.length && start + i < len &&
+ chrs(index + start + i) == chrs(prefix.start + i))
+ i += 1;
+ i == prefix.length
+ }
+
+ /** does this name end with suffix?
+ */
+ final def endsWith(suffix: Name): Boolean = endsWith(suffix, len)
+
+ /** does this name end with suffix just before given end index?
+ */
+ final def endsWith(suffix: Name, end: Int): Boolean = {
+ var i = 1
+ while (i <= suffix.length && i <= end &&
+ chrs(index + end - i) == chrs(suffix.start + suffix.length - i))
+ i += 1;
+ i > suffix.length
+ }
+
+ final def containsName(subname: String): Boolean = containsName(newTermName(subname))
+ final def containsName(subname: Name): Boolean = {
+ var start = 0
+ val last = len - subname.length
+ while (start <= last && !startsWith(subname, start)) start += 1
+ start <= last
+ }
+
+ /** Some thoroughly self-explanatory convenience functions. They
+ * assume that what they're being asked to do is known to be valid.
+ */
+ final def startChar: Char = apply(0)
+ final def endChar: Char = apply(len - 1)
+ final def startsWith(char: Char): Boolean = len > 0 && startChar == char
+ final def startsWith(name: String): Boolean = startsWith(newTermName(name))
+ final def endsWith(char: Char): Boolean = len > 0 && endChar == char
+ final def endsWith(name: String): Boolean = endsWith(newTermName(name))
+ final def stripStart(prefix: Name): Name = subName(prefix.length, len)
+ final def stripStart(prefix: String): Name = subName(prefix.length, len)
+ final def stripEnd(suffix: Name): Name = subName(0, len - suffix.length)
+ final def stripEnd(suffix: String): Name = subName(0, len - suffix.length)
+
+ def lastIndexOf(ch: Char) = toChars lastIndexOf ch
+
+ /** Return the subname with characters from start to end-1.
+ */
+ def subName(from: Int, to: Int): Name
+
+ /** Replace all occurrences of `from` by `to` in
+ * name; result is always a term name.
+ */
+ def replace(from: Char, to: Char): Name = {
+ val cs = new Array[Char](len)
+ var i = 0
+ while (i < len) {
+ val ch = this(i)
+ cs(i) = if (ch == from) to else ch
+ i += 1
+ }
+ newTermName(cs, 0, len)
+ }
+
+ /** Replace operator symbols by corresponding $op_name.
+ */
+ def encode: Name = {
+ val str = toString()
+ val res = NameTransformer.encode(str)
+ if (res == str) this
+ else if (isTypeName) newTypeName(res)
+ else newTermName(res)
+ }
+
+ def append(suffix: String): Name
+ def append(suffix: Name): Name
+
+ /** Replace $op_name by corresponding operator symbol.
+ */
+ def decode: String = (
+ NameTransformer.decode(toString()) +
+ (if (nameDebug && isTypeName) "!" else ""))//debug
+
+ def isOperatorName: Boolean = decode != toString
+ def nameKind: String = if (isTypeName) "type" else "term"
+ def longString: String = nameKind + " " + NameTransformer.decode(toString)
+ }
+
+ final class TermName(_index: Int, _len: Int, hash: Int) extends Name(_index, _len) {
+ var next: TermName = termHashtable(hash)
+ termHashtable(hash) = this
+ def isTermName: Boolean = true
+ def isTypeName: Boolean = false
+ def toTermName: TermName = this
+ def toTypeName: TypeName = {
+ val h = hashValue(chrs, index, len) & HASH_MASK
+ var n = typeHashtable(h)
+ while ((n ne null) && n.start != index)
+ n = n.next;
+ if (n eq null)
+ n = new TypeName(index, len, h);
+ n
+ }
+ def append(suffix: String): TermName = newTermName(this + suffix)
+ def append(suffix: Name): TermName = append(suffix.toString)
+ def companionName: TypeName = toTypeName
+ def subName(from: Int, to: Int): TermName =
+ newTermName(chrs, start + from, to - from)
+ }
+
+ final class TypeName(_index: Int, _len: Int, hash: Int) extends Name(_index, _len) {
+ var next: TypeName = typeHashtable(hash)
+ typeHashtable(hash) = this
+ def isTermName: Boolean = false
+ def isTypeName: Boolean = true
+ def toTermName: TermName = {
+ val h = hashValue(chrs, index, len) & HASH_MASK
+ var n = termHashtable(h)
+ while ((n ne null) && n.start != index)
+ n = n.next;
+ if (n eq null)
+ n = new TermName(index, len, h);
+ n
+ }
+ def toTypeName: TypeName = this
+
+ def append(suffix: String): TypeName = newTypeName(this + suffix)
+ def append(suffix: Name): TypeName = append(suffix.toString)
+ def companionName: TermName = toTermName
+ def subName(from: Int, to: Int): TypeName =
+ newTypeName(chrs, start + from, to - from)
+ }
+}
diff --git a/src/compiler/scala/reflect/common/Positions.scala b/src/compiler/scala/reflect/common/Positions.scala
new file mode 100644
index 0000000000..e8048a65c9
--- /dev/null
+++ b/src/compiler/scala/reflect/common/Positions.scala
@@ -0,0 +1,33 @@
+package scala.reflect
+package common
+
+trait Positions { self: SymbolTable =>
+
+ type Position
+ val NoPosition: Position
+
+ def focusPos(pos: Position): Position
+ def isRangePos(pos: Position): Boolean
+ def showPos(pos: Position): String
+
+ /** A position that wraps a set of trees.
+ * The point of the wrapping position is the point of the default position.
+ * If some of the trees are ranges, returns a range position enclosing all ranges
+ * Otherwise returns default position.
+ */
+ def wrappingPos(default: Position, trees: List[Tree]): Position = default
+
+ /** A position that wraps the non-empty set of trees.
+ * The point of the wrapping position is the point of the first trees' position.
+ * If all some the trees are non-synthetic, returns a range position enclosing the non-synthetic trees
+ * Otherwise returns a synthetic offset position to point.
+ */
+ def wrappingPos(trees: List[Tree]): Position = trees.head.pos
+
+ /** Ensure that given tree has no positions that overlap with
+ * any of the positions of `others`. This is done by
+ * shortening the range or assigning TransparentPositions
+ * to some of the nodes in `tree`.
+ */
+ def ensureNonOverlapping(tree: Tree, others: List[Tree]) {}
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/common/Required.scala b/src/compiler/scala/reflect/common/Required.scala
new file mode 100644
index 0000000000..a7d33fa8db
--- /dev/null
+++ b/src/compiler/scala/reflect/common/Required.scala
@@ -0,0 +1,17 @@
+package scala.reflect
+package common
+
+import settings.MutableSettings
+
+trait Required { self: SymbolTable =>
+
+ type AbstractFile >: Null <: { def path: String }
+
+ def picklerPhase: Phase
+
+ val treePrinter: TreePrinter
+
+ val gen: TreeGen { val global: Required.this.type }
+
+ def settings: MutableSettings
+}
diff --git a/src/compiler/scala/reflect/common/Scopes.scala b/src/compiler/scala/reflect/common/Scopes.scala
new file mode 100644
index 0000000000..4fbfa1760e
--- /dev/null
+++ b/src/compiler/scala/reflect/common/Scopes.scala
@@ -0,0 +1,326 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+trait Scopes { self: SymbolTable =>
+
+ class ScopeEntry(val sym: Symbol, val owner: Scope) {
+ /** the next entry in the hash bucket
+ */
+ var tail: ScopeEntry = null
+
+ /** the next entry in this scope
+ */
+ var next: ScopeEntry = null
+
+ override def hashCode(): Int = sym.name.start
+ override def toString(): String = sym.toString()
+ }
+
+ /**
+ * @param sym ...
+ * @param owner ...
+ * @return ...
+ */
+ private def newScopeEntry(sym: Symbol, owner: Scope): ScopeEntry = {
+ val e = new ScopeEntry(sym, owner)
+ e.next = owner.elems
+ owner.elems = e
+ e
+ }
+
+ class Scope(initElems: ScopeEntry) extends Iterable[Symbol] {
+
+ var elems: ScopeEntry = initElems
+
+ /** The number of times this scope is nested in another
+ */
+ private var nestinglevel = 0
+
+ /** the hash table
+ */
+ private var hashtable: Array[ScopeEntry] = null
+
+ /** a cache for all elements, to be used by symbol iterator.
+ */
+ private var elemsCache: List[Symbol] = null
+
+ /** size and mask of hash tables
+ * todo: make hashtables grow?
+ */
+ private val HASHSIZE = 0x80
+ private val HASHMASK = 0x7f
+
+ /** the threshold number of entries from which a hashtable is constructed.
+ */
+ private val MIN_HASH = 8
+
+ if (size >= MIN_HASH) createHash()
+
+ def this() = this(null: ScopeEntry)
+
+ def this(base: Scope) = {
+ this(base.elems)
+ nestinglevel = base.nestinglevel + 1
+ }
+
+ def this(decls: List[Symbol]) = {
+ this()
+ decls foreach enter
+ }
+
+ /** Returns a new scope with the same content as this one. */
+ def cloneScope: Scope = {
+ val clone = new Scope()
+ this.toList foreach (clone enter _)
+ clone
+ }
+
+ /** is the scope empty? */
+ override def isEmpty: Boolean = elems eq null
+
+ /** the number of entries in this scope */
+ override def size: Int = {
+ var s = 0
+ var e = elems
+ while (e ne null) {
+ s += 1
+ e = e.next
+ }
+ s
+ }
+
+ /** enter a scope entry
+ *
+ * @param e ...
+ */
+ def enter(e: ScopeEntry) {
+ elemsCache = null
+ if (hashtable ne null) {
+ val i = e.sym.name.start & HASHMASK
+ elems.tail = hashtable(i)
+ hashtable(i) = elems
+ } else if (size >= MIN_HASH) {
+ createHash()
+ }
+ }
+
+ /** enter a symbol
+ *
+ * @param sym ...
+ */
+ def enter(sym: Symbol): Symbol = { enter(newScopeEntry(sym, this)); sym }
+
+ /** enter a symbol, asserting that no symbol with same name exists in scope
+ *
+ * @param sym ...
+ */
+ def enterUnique(sym: Symbol) {
+ assert(lookup(sym.name) == NoSymbol)
+ enter(sym)
+ }
+
+ private def createHash() {
+ hashtable = new Array[ScopeEntry](HASHSIZE)
+ enterInHash(elems)
+ }
+
+ private def enterInHash(e: ScopeEntry) {
+ if (e ne null) {
+ enterInHash(e.next)
+ val i = e.sym.name.start & HASHMASK
+ e.tail = hashtable(i)
+ hashtable(i) = e
+ }
+ }
+
+ def rehash(sym: Symbol, newname: Name) {
+ if (hashtable ne null) {
+ val index = sym.name.start & HASHMASK
+ var e1 = hashtable(index)
+ var e: ScopeEntry = null
+ if (e1 != null) {
+ if (e1.sym == sym) {
+ hashtable(index) = e1.tail
+ e = e1
+ } else {
+ while (e1.tail != null && e1.tail.sym != sym) e1 = e1.tail
+ if (e1.tail != null) {
+ e = e1.tail
+ e1.tail = e.tail
+ }
+ }
+ }
+ if (e != null) {
+ val newindex = newname.start & HASHMASK
+ e.tail = hashtable(newindex)
+ hashtable(newindex) = e
+ }
+ }
+ }
+
+ /** remove entry
+ *
+ * @param e ...
+ */
+ def unlink(e: ScopeEntry) {
+ if (elems == e) {
+ elems = e.next
+ } else {
+ var e1 = elems
+ while (e1.next != e) e1 = e1.next
+ e1.next = e.next
+ }
+ if (hashtable ne null) {
+ val index = e.sym.name.start & HASHMASK
+ var e1 = hashtable(index)
+ if (e1 == e) {
+ hashtable(index) = e.tail
+ } else {
+ while (e1.tail != e) e1 = e1.tail;
+ e1.tail = e.tail
+ }
+ }
+ elemsCache = null
+ }
+
+ /** remove symbol */
+ def unlink(sym: Symbol) {
+ var e = lookupEntry(sym.name)
+ while (e ne null) {
+ if (e.sym == sym) unlink(e);
+ e = lookupNextEntry(e)
+ }
+ }
+
+ /** lookup a symbol
+ *
+ * @param name ...
+ * @return ...
+ */
+ def lookup(name: Name): Symbol = {
+ val e = lookupEntry(name)
+ if (e eq null) NoSymbol else e.sym
+ }
+
+ /** Returns an iterator yielding every symbol with given name in this scope.
+ */
+ def lookupAll(name: Name): Iterator[Symbol] = new Iterator[Symbol] {
+ var e = lookupEntry(name)
+ def hasNext: Boolean = e ne null
+ def next: Symbol = { val r = e.sym; e = lookupNextEntry(e); r }
+ }
+
+ /** lookup a symbol entry matching given name.
+ * @note from Martin: I believe this is a hotspot or will be one
+ * in future versions of the type system. I have reverted the previous
+ * change to use iterators as too costly.
+ */
+ def lookupEntry(name: Name): ScopeEntry = {
+ var e: ScopeEntry = null
+ if (hashtable ne null) {
+ e = hashtable(name.start & HASHMASK)
+ while ((e ne null) && e.sym.name != name) {
+ e = e.tail
+ }
+ } else {
+ e = elems
+ while ((e ne null) && e.sym.name != name) {
+ e = e.next
+ }
+ }
+ e
+ }
+
+ /** lookup next entry with same name as this one
+ * @note from Martin: I believe this is a hotspot or will be one
+ * in future versions of the type system. I have reverted the previous
+ * change to use iterators as too costly.
+ */
+ def lookupNextEntry(entry: ScopeEntry): ScopeEntry = {
+ var e = entry
+ if (hashtable ne null)
+ do { e = e.tail } while ((e ne null) && e.sym.name != entry.sym.name)
+ else
+ do { e = e.next } while ((e ne null) && e.sym.name != entry.sym.name);
+ e
+ }
+
+ /** Return all symbols as a list in the order they were entered in this scope.
+ */
+ override def toList: List[Symbol] = {
+ if (elemsCache eq null) {
+ elemsCache = Nil
+ var e = elems
+ while ((e ne null) && e.owner == this) {
+ elemsCache = e.sym :: elemsCache
+ e = e.next
+ }
+ }
+ elemsCache
+ }
+
+ /** Return the nesting level of this scope, i.e. the number of times this scope
+ * was nested in another */
+ def nestingLevel = nestinglevel
+
+ /** Return all symbols as an iterator in the order they were entered in this scope.
+ */
+ def iterator: Iterator[Symbol] = toList.iterator
+
+/*
+ /** Does this scope contain an entry for `sym`?
+ */
+ def contains(sym: Symbol): Boolean = lookupAll(sym.name) contains sym
+
+ /** A scope that contains all symbols of this scope and that also contains `sym`.
+ */
+ def +(sym: Symbol): Scope =
+ if (contains(sym)) this
+ else {
+ val result = cloneScope
+ result enter sym
+ result
+ }
+
+ /** A scope that contains all symbols of this scope except `sym`.
+ */
+ def -(sym: Symbol): Scope =
+ if (!contains(sym)) this
+ else {
+ val result = cloneScope
+ result unlink sym
+ result
+ }
+*/
+ override def foreach[U](p: Symbol => U): Unit = toList foreach p
+
+ override def filter(p: Symbol => Boolean): Scope =
+ if (!(toList forall p)) new Scope(toList filter p) else this
+
+ override def mkString(start: String, sep: String, end: String) =
+ toList.map(_.defString).mkString(start, sep, end)
+
+ override def toString(): String = mkString("Scope{\n ", ";\n ", "\n}")
+
+ }
+
+ def newScope: Scope = new Scope
+
+ /** The empty scope (immutable).
+ */
+ object EmptyScope extends Scope {
+ override def enter(e: ScopeEntry) {
+ abort("EmptyScope.enter")
+ }
+ }
+
+ /** The error scope.
+ */
+ class ErrorScope(owner: Symbol) extends Scope(null: ScopeEntry)
+}
+
diff --git a/src/compiler/scala/reflect/common/StdNames.scala b/src/compiler/scala/reflect/common/StdNames.scala
new file mode 100644
index 0000000000..5c1efa35ba
--- /dev/null
+++ b/src/compiler/scala/reflect/common/StdNames.scala
@@ -0,0 +1,617 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+import scala.collection.immutable
+
+trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: SymbolTable =>
+
+ def encode(str: String): TermName = newTermName(NameTransformer.encode(str))
+
+ implicit def stringToTermName(s: String): TermName = newTermName(s)
+
+ /** This should be the first trait in the linearization. */
+ trait Keywords {
+ private var kws: Set[TermName] = Set()
+ private def kw(s: String): TermName = {
+ val result = newTermName(s)
+ kws = kws + result
+ result
+ }
+
+ final val ABSTRACTkw: TermName = kw("abstract")
+ final val CASEkw: TermName = kw("case")
+ final val CLASSkw: TermName = kw("class")
+ final val CATCHkw: TermName = kw("catch")
+ final val DEFkw: TermName = kw("def")
+ final val DOkw: TermName = kw("do")
+ final val ELSEkw: TermName = kw("else")
+ final val EXTENDSkw: TermName = kw("extends")
+ final val FALSEkw: TermName = kw("false")
+ final val FINALkw: TermName = kw("final")
+ final val FINALLYkw: TermName = kw("finally")
+ final val FORkw: TermName = kw("for")
+ final val FORSOMEkw: TermName = kw("forSome")
+ final val IFkw: TermName = kw("if")
+ final val IMPLICITkw: TermName = kw("implicit")
+ final val IMPORTkw: TermName = kw("import")
+ final val LAZYkw: TermName = kw("lazy")
+ final val MATCHkw: TermName = kw("match")
+ final val NEWkw: TermName = kw("new")
+ final val NULLkw: TermName = kw("null")
+ final val OBJECTkw: TermName = kw("object")
+ final val OVERRIDEkw: TermName = kw("override")
+ final val PACKAGEkw: TermName = kw("package")
+ final val PRIVATEkw: TermName = kw("private")
+ final val PROTECTEDkw: TermName = kw("protected")
+ final val RETURNkw: TermName = kw("return")
+ final val SEALEDkw: TermName = kw("sealed")
+ final val SUPERkw: TermName = kw("super")
+ final val THISkw: TermName = kw("this")
+ final val THROWkw: TermName = kw("throw")
+ final val TRAITkw: TermName = kw("trait")
+ final val TRUEkw: TermName = kw("true")
+ final val TRYkw: TermName = kw("try")
+ final val TYPEkw: TermName = kw("type")
+ final val VALkw: TermName = kw("val")
+ final val VARkw: TermName = kw("var")
+ final val WITHkw: TermName = kw("with")
+ final val WHILEkw: TermName = kw("while")
+ final val YIELDkw: TermName = kw("yield")
+ final val DOTkw: TermName = kw(".")
+ final val USCOREkw: TermName = kw("_")
+ final val COLONkw: TermName = kw(":")
+ final val EQUALSkw: TermName = kw("=")
+ final val ARROWkw: TermName = kw("=>")
+ final val LARROWkw: TermName = kw("<-")
+ final val SUBTYPEkw: TermName = kw("<:")
+ final val VIEWBOUNDkw: TermName = kw("<%")
+ final val SUPERTYPEkw: TermName = kw(">:")
+ final val HASHkw: TermName = kw("#")
+ final val ATkw: TermName = kw("@")
+
+ final val keywords = {
+ val result = kws.toSet
+ kws = null
+ result
+ }
+
+ final val javaKeywords = new JavaKeywords()
+ }
+
+ trait CommonNames /*extends LibraryCommonNames*/ {
+
+ type NameType <: Name
+ implicit def createNameType(name: String): NameType
+
+ val EMPTY: NameType = ""
+ val ANON_FUN_NAME: NameType = "$anonfun"
+ val EMPTY_PACKAGE_NAME: NameType = "<empty>"
+ val IMPORT: NameType = "<import>"
+ val MODULE_SUFFIX: NameType = "$module"
+ val ROOT: NameType = "<root>"
+
+ // value types are all used as terms as well
+ final val Boolean: NameType = "Boolean"
+ final val Byte: NameType = "Byte"
+ final val Char: NameType = "Char"
+ final val Double: NameType = "Double"
+ final val Float: NameType = "Float"
+ final val Int: NameType = "Int"
+ final val Long: NameType = "Long"
+ final val Short: NameType = "Short"
+ final val Unit: NameType = "Unit"
+
+ final val ScalaValueNames: scala.List[NameType] =
+ scala.List(Byte, Char, Short, Int, Long, Float, Double, Boolean, Unit)
+
+ // types whose companions we utilize
+ final val Array: NameType = "Array"
+ final val List: NameType = "List"
+ final val Seq: NameType = "Seq"
+ final val Symbol: NameType = "Symbol"
+
+ // fictions we use as both types and terms
+ final val ERROR: NameType = "<error>"
+ final val NO_NAME: NameType = "<none>" // formerly NOSYMBOL
+ final val WILDCARD: NameType = "_"
+ }
+
+ trait TypeNames extends CommonNames {
+ final val BYNAME_PARAM_CLASS_NAME: NameType = "<byname>"
+ final val EQUALS_PATTERN_NAME: NameType = "<equals>"
+ final val JAVA_REPEATED_PARAM_CLASS_NAME: NameType = "<repeated...>"
+ final val LOCAL_CHILD: NameType = "<local child>"
+ final val REPEATED_PARAM_CLASS_NAME: NameType = "<repeated>"
+ final val WILDCARD_STAR: NameType = "_*"
+
+ final val Any: NameType = "Any"
+ final val AnyRef: NameType = "AnyRef"
+ final val AnyVal: NameType = "AnyVal"
+ final val Nothing: NameType = "Nothing"
+ final val Null: NameType = "Null"
+ final val Object: NameType = "Object"
+ final val PartialFunction: NameType = "PartialFunction"
+ final val Product: NameType = "Product"
+ final val ScalaObject: NameType = "ScalaObject"
+ final val Serializable: NameType = "Serializable"
+ final val Singleton: NameType = "Singleton"
+ final val String: NameType = "String"
+ final val Throwable: NameType = "Throwable"
+
+ // Annotation types
+ final val AnnotationDefaultATTR: NameType = "AnnotationDefault"
+ final val BridgeATTR: NameType = "Bridge"
+ final val ClassfileAnnotationATTR: NameType = "RuntimeInvisibleAnnotations" // RetentionPolicy.CLASS. Currently not used (Apr 2009).
+ final val CodeATTR: NameType = "Code"
+ final val ConstantValueATTR: NameType = "ConstantValue"
+ final val DeprecatedATTR: NameType = "Deprecated"
+ final val ExceptionsATTR: NameType = "Exceptions"
+ final val InnerClassesATTR: NameType = "InnerClasses"
+ final val JacoMetaATTR: NameType = "JacoMeta"
+ final val LineNumberTableATTR: NameType = "LineNumberTable"
+ final val LocalVariableTableATTR: NameType = "LocalVariableTable"
+ final val RuntimeAnnotationATTR: NameType = "RuntimeVisibleAnnotations" // RetentionPolicy.RUNTIME
+ final val RuntimeParamAnnotationATTR: NameType = "RuntimeVisibleParameterAnnotations" // RetentionPolicy.RUNTIME (annotations on parameters)
+ final val ScalaATTR: NameType = "Scala"
+ final val ScalaSignatureATTR: NameType = "ScalaSig"
+ final val SignatureATTR: NameType = "Signature"
+ final val SourceFileATTR: NameType = "SourceFile"
+ final val SyntheticATTR: NameType = "Synthetic"
+ }
+
+
+ trait TermNames extends Keywords with CommonNames {
+ // Compiler internal names
+ val ANYNAME: NameType = "<anyname>"
+ val CONSTRUCTOR: NameType = "<init>"
+ val FAKE_LOCAL_THIS: NameType = "this$"
+ val INITIALIZER: NameType = CONSTRUCTOR // Is this buying us something?
+ val MIXIN_CONSTRUCTOR: NameType = "$init$"
+ val MODULE_INSTANCE_FIELD: NameType = "MODULE$"
+ val OUTER: NameType = "$outer"
+ val OUTER_LOCAL: NameType = "$outer " // note the space
+ val SELF: NameType = "$this"
+ val SPECIALIZED_INSTANCE: NameType = "specInstance$"
+ val STAR: NameType = "*"
+ val THIS: NameType = "_$this"
+
+ final val Nil: NameType = "Nil"
+ final val Predef: NameType = "Predef"
+ final val ScalaRunTime: NameType = "ScalaRunTime"
+ final val Some: NameType = "Some"
+
+ // Compiler utilized names
+ // val productElementName: NameType = "productElementName"
+ val TYPE_ : NameType = "TYPE"
+ val add_ : NameType = "add"
+ val apply: NameType = "apply"
+ val arrayValue: NameType = "arrayValue"
+ val arraycopy: NameType = "arraycopy"
+ val asInstanceOf_ : NameType = "asInstanceOf"
+ val assert_ : NameType = "assert"
+ val assume_ : NameType = "assume"
+ val box: NameType = "box"
+ val bytes: NameType = "bytes"
+ val canEqual_ : NameType = "canEqual"
+ val checkInitialized: NameType = "checkInitialized"
+ val classOf: NameType = "classOf"
+ val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure
+ val conforms: NameType = "conforms"
+ val copy: NameType = "copy"
+ val delayedInit: NameType = "delayedInit"
+ val delayedInitArg: NameType = "delayedInit$body"
+ val drop: NameType = "drop"
+ val elem: NameType = "elem"
+ val eq: NameType = "eq"
+ val equals_ : NameType = if (forMSIL) "Equals" else "equals"
+ val error: NameType = "error"
+ val ex: NameType = "ex"
+ val false_ : NameType = "false"
+ val filter: NameType = "filter"
+ val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize"
+ val find_ : NameType = "find"
+ val flatMap: NameType = "flatMap"
+ val foreach: NameType = "foreach"
+ val genericArrayOps: NameType = "genericArrayOps"
+ val get: NameType = "get"
+ val hasNext: NameType = "hasNext"
+ val hashCode_ : NameType = if (forMSIL) "GetHashCode" else "hashCode"
+ val hash_ : NameType = "hash"
+ val head: NameType = "head"
+ val identity: NameType = "identity"
+ val inlinedEquals: NameType = "inlinedEquals"
+ val applyDynamic: NameType = "applyDynamic"
+ val isArray: NameType = "isArray"
+ val isDefinedAt: NameType = "isDefinedAt"
+ val isEmpty: NameType = "isEmpty"
+ val isInstanceOf_ : NameType = "isInstanceOf"
+ val java: NameType = "java"
+ val lang: NameType = "lang"
+ val length: NameType = "length"
+ val lengthCompare: NameType = "lengthCompare"
+ val lift_ : NameType = "lift"
+ val main: NameType = "main"
+ val map: NameType = "map"
+ val ne: NameType = "ne"
+ val newArray: NameType = "newArray"
+ val next: NameType = "next"
+ val notifyAll_ : NameType = "notifyAll"
+ val notify_ : NameType = "notify"
+ val null_ : NameType = "null"
+ val ofDim: NameType = "ofDim"
+ val productArity: NameType = "productArity"
+ val productElement: NameType = "productElement"
+ val productPrefix: NameType = "productPrefix"
+ val readResolve: NameType = "readResolve"
+ val sameElements: NameType = "sameElements"
+ val scala_ : NameType = "scala"
+ val self: NameType = "self"
+ val setAccessible: NameType = "setAccessible"
+ val synchronized_ : NameType = "synchronized"
+ val tail: NameType = "tail"
+ val this_ : NameType = "this"
+ val throw_ : NameType = "throw"
+ val toArray: NameType = "toArray"
+ val toList: NameType = "toList"
+ val toSeq: NameType = "toSeq"
+ val toString_ : NameType = if (forMSIL) "ToString" else "toString"
+ val true_ : NameType = "true"
+ val unapply: NameType = "unapply"
+ val unapplySeq: NameType = "unapplySeq"
+ val unbox: NameType = "unbox"
+ val update: NameType = "update"
+ val value: NameType = "value"
+ val view_ : NameType = "view"
+ val wait_ : NameType = "wait"
+ val withFilter: NameType = "withFilter"
+ val wrapRefArray: NameType = "wrapRefArray"
+ val zip: NameType = "zip"
+
+ // unencoded operators
+ object raw {
+ final val AMP : NameType = "&"
+ final val BANG : NameType = "!"
+ final val BAR : NameType = "|"
+ final val DOLLAR: NameType = "$"
+ final val GE: NameType = ">="
+ final val LE: NameType = "<="
+ final val MINUS: NameType = "-"
+ final val NE: NameType = "!="
+ final val PLUS : NameType = "+"
+ final val SLASH: NameType = "/"
+ final val STAR : NameType = "*"
+ final val TILDE: NameType = "~"
+
+ final val isUnary: Set[Name] = Set(MINUS, PLUS, TILDE, BANG)
+ }
+
+ // value-conversion methods
+ val toByte: NameType = "toByte"
+ val toShort: NameType = "toShort"
+ val toChar: NameType = "toChar"
+ val toInt: NameType = "toInt"
+ val toLong: NameType = "toLong"
+ val toFloat: NameType = "toFloat"
+ val toDouble: NameType = "toDouble"
+ }
+
+ object tpnme extends TypeNames /*with LibraryTypeNames*/ with TypeNameMangling {
+ type NameType = TypeName
+ implicit def createNameType(name: String): TypeName = newTypeName(name)
+
+ val REFINE_CLASS_NAME: NameType = "<refinement>"
+ val ANON_CLASS_NAME: NameType = "$anon"
+ }
+
+ val javanme = nme.javaKeywords
+
+ object nme extends TermNames /*with LibraryTermNames*/ with TermNameMangling {
+ type NameType = TermName
+ def createNameType(name: String): TermName = newTermName(name)
+
+ /** Translate a String into a list of simple TypeNames and TermNames.
+ * In all segments before the last, type/term is determined by whether
+ * the following separator char is '.' or '#'. In the last segment,
+ * the argument "assumeTerm" determines it. Examples:
+ *
+ * package foo {
+ * object Lorax { object Wog ; class Wog }
+ * class Lorax { object Zax ; class Zax }
+ * }
+ *
+ * f("foo.Lorax", true) == List("foo": Term, "Lorax": Term) // object Lorax
+ * f("foo.Lorax", false) == List("foo": Term, "Lorax": Type) // class Lorax
+ * f("Lorax.Wog", true) == List("Lorax": Term, "Wog": Term) // object Wog
+ * f("Lorax.Wog", false) == List("Lorax": Term, "Wog": Type) // class Wog
+ * f("Lorax#Zax", true) == List("Lorax": Type, "Zax": Term) // object Zax
+ * f("Lorax#Zax", false) == List("Lorax": Type, "Zax": Type) // class Zax
+ *
+ * Note that in actual scala syntax you cannot refer to object Zax without an
+ * instance of Lorax, so Lorax#Zax could only mean the type. One might think
+ * that Lorax#Zax.type would work, but this is not accepted by the parser.
+ * For the purposes of referencing that object, the syntax is allowed.
+ */
+ def segments(name: String, assumeTerm: Boolean): List[Name] = {
+ def mkName(str: String, term: Boolean): Name =
+ if (term) newTermName(str) else newTypeName(str)
+
+ name.indexWhere(ch => ch == '.' || ch == '#') match {
+ // it's the last segment: the parameter tells us whether type or term
+ case -1 => if (name == "") scala.Nil else scala.List(mkName(name, assumeTerm))
+ // otherwise, we can tell based on whether '#' or '.' is the following char.
+ case idx =>
+ val (simple, div, rest) = (name take idx, name charAt idx, name drop (idx + 1))
+ mkName(simple, div == '.') :: segments(rest, assumeTerm)
+ }
+ }
+ private def bitmapName(n: Int, suffix: String): TermName =
+ newTermName(BITMAP_PREFIX + suffix + n)
+
+ /** The name of bitmaps for initialized (public or protected) lazy vals. */
+ def bitmapName(n: Int): TermName = bitmapName(n, "")
+
+ /** The name of bitmaps for initialized transient lazy vals. */
+ def bitmapNameForTransient(n: Int): TermName = bitmapName(n, "trans$")
+
+ /** The name of bitmaps for initialized private lazy vals. */
+ def bitmapNameForPrivate(n: Int): TermName = bitmapName(n, "priv$")
+
+ /** The name of bitmaps for checkinit values */
+ def bitmapNameForCheckinit(n: Int): TermName = bitmapName(n, "init$")
+
+ /** The name of bitmaps for checkinit values that have transient flag*/
+ def bitmapNameForCheckinitTransient(n: Int): TermName = bitmapName(n, "inittrans$")
+
+ /** The expanded name of `name' relative to this class `base` with given `separator`
+ */
+ def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName =
+ newTermName(base.fullName('$') + separator + name)
+
+ def moduleVarName(name: TermName): TermName = newTermName("" + name + MODULE_SUFFIX)
+
+ val EXPAND_SEPARATOR_STRING = "$$"
+ val LOCAL_SUFFIX_STRING = " "
+ val ROOTPKG: TermName = "_root_"
+
+ /** Base strings from which synthetic names are derived. */
+ val BITMAP_PREFIX = "bitmap$"
+ val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$"
+ val DEFAULT_GETTER_STRING = "$default$"
+ val DO_WHILE_PREFIX = "doWhile$"
+ val EQEQ_LOCAL_VAR = "eqEqTemp$"
+ val EVIDENCE_PARAM_PREFIX = "evidence$"
+ val EXCEPTION_RESULT_PREFIX = "exceptionResult"
+ val INTERPRETER_IMPORT_WRAPPER = "$iw"
+ val INTERPRETER_LINE_PREFIX = "line"
+ val INTERPRETER_SYNTHVAR_PREFIX = "synthvar$"
+ val INTERPRETER_VAR_PREFIX = "res"
+ val INTERPRETER_WRAPPER_SUFFIX = "$object"
+ val WHILE_PREFIX = "while$"
+
+ def getCause = sn.GetCause
+ def getClass_ = sn.GetClass
+ def getMethod_ = sn.GetMethod
+ def invoke_ = sn.Invoke
+
+ val ADD = encode("+")
+ val AND = encode("&")
+ val ASR = encode(">>")
+ val DIV = encode("/")
+ val EQ = encode("==")
+ val EQL = encode("=")
+ val GE = encode(">=")
+ val GT = encode(">")
+ val HASHHASH = encode("##")
+ val LE = encode("<=")
+ val LSL = encode("<<")
+ val LSR = encode(">>>")
+ val LT = encode("<")
+ val MINUS = encode("-")
+ val MOD = encode("%")
+ val MUL = encode("*")
+ val NE = encode("!=")
+ val OR = encode("|")
+ val PLUS = encode("+")
+ val SUB = encode("-")
+ val XOR = encode("^")
+ val ZAND = encode("&&")
+ val ZOR = encode("||")
+
+ // unary operators
+ val UNARY_~ = encode("unary_~")
+ val UNARY_+ = encode("unary_+")
+ val UNARY_- = encode("unary_-")
+ val UNARY_! = encode("unary_!")
+ }
+
+ abstract class SymbolNames {
+ protected implicit def stringToTypeName(s: String): TypeName = newTypeName(s)
+
+ val BeanProperty : TypeName
+ val BooleanBeanProperty : TypeName
+ val BoxedBoolean : TypeName
+ val BoxedCharacter : TypeName
+ val BoxedNumber : TypeName
+ val Class : TypeName
+ val Code : TypeName
+ val Delegate : TypeName
+ val IOOBException : TypeName // IndexOutOfBoundsException
+ val InvTargetException : TypeName // InvocationTargetException
+ val JavaSerializable : TypeName
+ val MethodAsObject : TypeName
+ val NPException : TypeName // NullPointerException
+ val Object : TypeName
+ val String : TypeName
+ val Throwable : TypeName
+ val ValueType : TypeName
+
+ val ForName : TermName
+ val GetCause : TermName
+ val GetClass : TermName
+ val GetMethod : TermName
+ val Invoke : TermName
+ val JavaLang : TermName
+
+ val Boxed: immutable.Map[TypeName, TypeName]
+ }
+
+ class JavaKeywords {
+ private var kws: Set[TermName] = Set()
+ private def kw(s: String): TermName = {
+ val result = newTermName(s)
+ kws = kws + result
+ result
+ }
+
+ final val ABSTRACTkw: TermName = kw("abstract")
+ final val ASSERTkw: TermName = kw("assert")
+ final val BOOLEANkw: TermName = kw("boolean")
+ final val BREAKkw: TermName = kw("break")
+ final val BYTEkw: TermName = kw("byte")
+ final val CASEkw: TermName = kw("case")
+ final val CATCHkw: TermName = kw("catch")
+ final val CHARkw: TermName = kw("char")
+ final val CLASSkw: TermName = kw("class")
+ final val CONSTkw: TermName = kw("const")
+ final val CONTINUEkw: TermName = kw("continue")
+ final val DEFAULTkw: TermName = kw("default")
+ final val DOkw: TermName = kw("do")
+ final val DOUBLEkw: TermName = kw("double")
+ final val ELSEkw: TermName = kw("else")
+ final val ENUMkw: TermName = kw("enum")
+ final val EXTENDSkw: TermName = kw("extends")
+ final val FINALkw: TermName = kw("final")
+ final val FINALLYkw: TermName = kw("finally")
+ final val FLOATkw: TermName = kw("float")
+ final val FORkw: TermName = kw("for")
+ final val IFkw: TermName = kw("if")
+ final val GOTOkw: TermName = kw("goto")
+ final val IMPLEMENTSkw: TermName = kw("implements")
+ final val IMPORTkw: TermName = kw("import")
+ final val INSTANCEOFkw: TermName = kw("instanceof")
+ final val INTkw: TermName = kw("int")
+ final val INTERFACEkw: TermName = kw("interface")
+ final val LONGkw: TermName = kw("long")
+ final val NATIVEkw: TermName = kw("native")
+ final val NEWkw: TermName = kw("new")
+ final val PACKAGEkw: TermName = kw("package")
+ final val PRIVATEkw: TermName = kw("private")
+ final val PROTECTEDkw: TermName = kw("protected")
+ final val PUBLICkw: TermName = kw("public")
+ final val RETURNkw: TermName = kw("return")
+ final val SHORTkw: TermName = kw("short")
+ final val STATICkw: TermName = kw("static")
+ final val STRICTFPkw: TermName = kw("strictfp")
+ final val SUPERkw: TermName = kw("super")
+ final val SWITCHkw: TermName = kw("switch")
+ final val SYNCHRONIZEDkw: TermName = kw("synchronized")
+ final val THISkw: TermName = kw("this")
+ final val THROWkw: TermName = kw("throw")
+ final val THROWSkw: TermName = kw("throws")
+ final val TRANSIENTkw: TermName = kw("transient")
+ final val TRYkw: TermName = kw("try")
+ final val VOIDkw: TermName = kw("void")
+ final val VOLATILEkw: TermName = kw("volatile")
+ final val WHILEkw: TermName = kw("while")
+
+ final val keywords = {
+ val result = kws.toSet
+ kws = null
+ result
+ }
+ }
+
+ private abstract class JavaNames extends SymbolNames {
+ final val BoxedBoolean: TypeName = "java.lang.Boolean"
+ final val BoxedByte: TypeName = "java.lang.Byte"
+ final val BoxedCharacter: TypeName = "java.lang.Character"
+ final val BoxedDouble: TypeName = "java.lang.Double"
+ final val BoxedFloat: TypeName = "java.lang.Float"
+ final val BoxedInteger: TypeName = "java.lang.Integer"
+ final val BoxedLong: TypeName = "java.lang.Long"
+ final val BoxedNumber: TypeName = "java.lang.Number"
+ final val BoxedShort: TypeName = "java.lang.Short"
+ final val Class: TypeName = "java.lang.Class"
+ final val Delegate: TypeName = tpnme.NO_NAME
+ final val IOOBException: TypeName = "java.lang.IndexOutOfBoundsException"
+ final val InvTargetException: TypeName = "java.lang.reflect.InvocationTargetException"
+ final val MethodAsObject: TypeName = "java.lang.reflect.Method"
+ final val NPException: TypeName = "java.lang.NullPointerException"
+ final val Object: TypeName = "java.lang.Object"
+ final val String: TypeName = "java.lang.String"
+ final val Throwable: TypeName = "java.lang.Throwable"
+ final val ValueType: TypeName = tpnme.NO_NAME
+
+ final val ForName: TermName = "forName"
+ final val GetCause: TermName = "getCause"
+ final val GetClass: TermName = "getClass"
+ final val GetMethod: TermName = "getMethod"
+ final val Invoke: TermName = "invoke"
+ final val JavaLang: TermName = "java.lang"
+
+ val Boxed = immutable.Map[TypeName, TypeName](
+ tpnme.Boolean -> BoxedBoolean,
+ tpnme.Byte -> BoxedByte,
+ tpnme.Char -> BoxedCharacter,
+ tpnme.Short -> BoxedShort,
+ tpnme.Int -> BoxedInteger,
+ tpnme.Long -> BoxedLong,
+ tpnme.Float -> BoxedFloat,
+ tpnme.Double -> BoxedDouble
+ )
+ }
+
+ private class MSILNames extends SymbolNames {
+ final val BeanProperty: TypeName = tpnme.NO_NAME
+ final val BooleanBeanProperty: TypeName = tpnme.NO_NAME
+ final val BoxedBoolean: TypeName = "System.IConvertible"
+ final val BoxedCharacter: TypeName = "System.IConvertible"
+ final val BoxedNumber: TypeName = "System.IConvertible"
+ final val Class: TypeName = "System.Type"
+ final val Code: TypeName = tpnme.NO_NAME
+ final val Delegate: TypeName = "System.MulticastDelegate"
+ final val IOOBException: TypeName = "System.IndexOutOfRangeException"
+ final val InvTargetException: TypeName = "System.Reflection.TargetInvocationException"
+ final val JavaSerializable: TypeName = tpnme.NO_NAME
+ final val MethodAsObject: TypeName = "System.Reflection.MethodInfo"
+ final val NPException: TypeName = "System.NullReferenceException"
+ final val Object: TypeName = "System.Object"
+ final val String: TypeName = "System.String"
+ final val Throwable: TypeName = "System.Exception"
+ final val ValueType: TypeName = "System.ValueType"
+
+ final val ForName: TermName = "GetType"
+ final val GetCause: TermName = "InnerException" /* System.Reflection.TargetInvocationException.InnerException */
+ final val GetClass: TermName = "GetType"
+ final val GetMethod: TermName = "GetMethod"
+ final val Invoke: TermName = "Invoke"
+ final val JavaLang: TermName = "System"
+
+ val Boxed = immutable.Map[TypeName, TypeName](
+ tpnme.Boolean -> "System.Boolean",
+ tpnme.Byte -> "System.SByte", // a scala.Byte is signed and a System.SByte too (unlike a System.Byte)
+ tpnme.Char -> "System.Char",
+ tpnme.Short -> "System.Int16",
+ tpnme.Int -> "System.Int32",
+ tpnme.Long -> "System.Int64",
+ tpnme.Float -> "System.Single",
+ tpnme.Double -> "System.Double"
+ )
+ }
+
+ private class J2SENames extends JavaNames {
+ final val BeanProperty: TypeName = "scala.reflect.BeanProperty"
+ final val BooleanBeanProperty: TypeName = "scala.reflect.BooleanBeanProperty"
+ final val Code: TypeName = "scala.reflect.Code"
+ final val JavaSerializable: TypeName = "java.io.Serializable"
+ }
+
+ lazy val sn: SymbolNames =
+ if (forMSIL) new MSILNames
+ else new J2SENames
+}
diff --git a/src/compiler/scala/reflect/common/SymbolTable.scala b/src/compiler/scala/reflect/common/SymbolTable.scala
new file mode 100644
index 0000000000..4bbe0b5201
--- /dev/null
+++ b/src/compiler/scala/reflect/common/SymbolTable.scala
@@ -0,0 +1,112 @@
+/* NSC -- new scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+import util._
+
+abstract class SymbolTable extends /*reflect.generic.Universe
+ with*/ Names
+ with Symbols
+ with Types
+ with Scopes
+ with Caches
+ with Definitions
+ with Constants
+ with BaseTypeSeqs
+ with InfoTransformers
+ with StdNames
+ with AnnotationInfos
+ with AnnotationCheckers
+ with Trees
+ with TreePrinters
+ with Positions
+ with TypeDebugging
+ with Required
+{
+ def rootLoader: LazyType
+ def log(msg: => AnyRef)
+ def abort(msg: String): Nothing = throw new Error(msg)
+ def abort(): Nothing = throw new Error()
+
+ /** Are we compiling for Java SE ? */
+ // def forJVM: Boolean
+
+ /** Are we compiling for .NET ? */
+ def forMSIL: Boolean = false
+
+ /** A period is an ordinal number for a phase in a run.
+ * Phases in later runs have higher periods than phases in earlier runs.
+ * Later phases have higher periods than earlier phases in the same run.
+ */
+ type Period = Int
+ final val NoPeriod = 0
+
+ /** An ordinal number for compiler runs. First run has number 1. */
+ type RunId = Int
+ final val NoRunId = 0
+
+ private var ph: Phase = NoPhase
+ private var per = NoPeriod
+
+ final def phase: Phase = ph
+
+ final def phase_=(p: Phase) {
+ //System.out.println("setting phase to " + p)
+ assert((p ne null) && p != NoPhase)
+ ph = p
+ per = (currentRunId << 8) + p.id
+ }
+
+ /** The current compiler run identifier. */
+ def currentRunId: RunId
+
+ /** The run identifier of the given period */
+ final def runId(period: Period): RunId = period >> 8
+
+ /** The phase identifier of the given period */
+ final def phaseId(period: Period): Phase#Id = period & 0xFF
+
+ /** The period at the start of run that includes `period' */
+ final def startRun(period: Period): Period = period & 0xFFFFFF00
+
+ /** The current period */
+ final def currentPeriod: Period = {
+ //assert(per == (currentRunId << 8) + phase.id)
+ per
+ }
+
+ /** The phase associated with given period */
+ final def phaseOf(period: Period): Phase = phaseWithId(phaseId(period))
+
+ final def period(rid: RunId, pid: Phase#Id): Period =
+ (currentRunId << 8) + pid
+
+ /** Perform given operation at given phase */
+ final def atPhase[T](ph: Phase)(op: => T): T = {
+ val current = phase
+ phase = ph
+ try op
+ finally phase = current
+ }
+ final def afterPhase[T](ph: Phase)(op: => T): T =
+ atPhase(ph.next)(op)
+
+ /** Break into repl debugger if assertion is true */
+ // def breakIf(assertion: => Boolean, args: Any*): Unit =
+ // if (assertion)
+ // ILoop.break(args.toList)
+
+ /** The set of all installed infotransformers */
+ var infoTransformers = new InfoTransformer {
+ val pid = NoPhase.id
+ val changesBaseClasses = true
+ def transform(sym: Symbol, tpe: Type): Type = tpe
+ }
+
+ /** The phase which has given index as identifier */
+ val phaseWithId: Array[Phase]
+}
diff --git a/src/compiler/scala/reflect/common/Symbols.scala b/src/compiler/scala/reflect/common/Symbols.scala
new file mode 100644
index 0000000000..573871fa8b
--- /dev/null
+++ b/src/compiler/scala/reflect/common/Symbols.scala
@@ -0,0 +1,2275 @@
+ /* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+
+package scala.reflect
+package common
+
+import scala.collection.{ mutable, immutable }
+import scala.collection.mutable.ListBuffer
+import util.Statistics._
+import Flags._
+
+trait Symbols /* extends reflect.generic.Symbols*/ { self: SymbolTable =>
+ import definitions._
+
+ private var ids = 0
+ def symbolCount = ids // statistics
+
+ val emptySymbolArray = new Array[Symbol](0)
+
+ /** Used for deciding in the IDE whether we can interrupt the compiler */
+ //protected var activeLocks = 0
+
+ /** Used for debugging only */
+ //protected var lockedSyms = collection.immutable.Set[Symbol]()
+
+ /** Used to keep track of the recursion depth on locked symbols */
+ private var recursionTable = immutable.Map.empty[Symbol, Int]
+
+ private var nextexid = 0
+ private def freshExistentialName(suffix: String) = {
+ nextexid += 1
+ newTypeName("_" + nextexid + suffix)
+ }
+
+ /** The original owner of a class. Used by the backend to generate
+ * EnclosingMethod attributes.
+ */
+ val originalOwner = mutable.HashMap[Symbol, Symbol]()
+
+ /** The class for all symbols */
+ abstract class Symbol(initOwner: Symbol, initPos: Position, initName: Name) extends HasFlags /*AbsSymbol */ {
+
+ type FlagsType = Long
+ type AccessBoundaryType = Symbol
+ type AnnotationType = AnnotationInfo
+
+ var rawowner = initOwner
+ var rawname = initName
+ var rawflags = 0L
+
+ private var rawpos = initPos
+ val id = { ids += 1; ids } // identity displayed when -uniqid
+
+ var validTo: Period = NoPeriod
+
+ def pos = rawpos
+ def setPos(pos: Position): this.type = { this.rawpos = pos; this }
+
+// ------ creators -------------------------------------------------------------------
+
+ final def newValue(pos: Position, name: TermName) =
+ new TermSymbol(this, pos, name)
+ final def newValue(name: TermName, pos: Position = NoPosition) =
+ new TermSymbol(this, pos, name)
+ final def newVariable(pos: Position, name: TermName) =
+ newValue(pos, name).setFlag(MUTABLE)
+ final def newValueParameter(pos: Position, name: TermName) =
+ newValue(pos, name).setFlag(PARAM)
+ /** Create local dummy for template (owner of local blocks) */
+ final def newLocalDummy(pos: Position) =
+ newValue(pos, nme.localDummyName(this)).setInfo(NoType)
+ final def newMethod(pos: Position, name: TermName) =
+ new MethodSymbol(this, pos, name).setFlag(METHOD)
+ final def newMethod(name: TermName, pos: Position = NoPosition) =
+ new MethodSymbol(this, pos, name).setFlag(METHOD)
+ final def newLabel(pos: Position, name: TermName) =
+ newMethod(pos, name).setFlag(LABEL)
+ final def newConstructor(pos: Position) =
+ newMethod(pos, nme.CONSTRUCTOR)
+ final def newModule(pos: Position, name: TermName, clazz: ClassSymbol) =
+ new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
+ .setModuleClass(clazz)
+ final def newModule(name: TermName, clazz: Symbol, pos: Position = NoPosition) =
+ new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
+ .setModuleClass(clazz.asInstanceOf[ClassSymbol])
+ final def newModule(pos: Position, name: TermName) = {
+ val m = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
+ m.setModuleClass(new ModuleClassSymbol(m))
+ }
+ final def newPackage(pos: Position, name: TermName) = {
+ assert(name == nme.ROOT || isPackageClass)
+ val m = newModule(pos, name).setFlag(JAVA | PACKAGE)
+ m.moduleClass.setFlag(JAVA | PACKAGE)
+ m
+ }
+ final def newThisSym(pos: Position) =
+ newValue(pos, nme.this_).setFlag(SYNTHETIC)
+ final def newImport(pos: Position) =
+ newValue(pos, nme.IMPORT)
+
+ /** @param pre type relative to which alternatives are seen.
+ * for instance:
+ * class C[T] {
+ * def m(x: T): T
+ * def m'(): T
+ * }
+ * val v: C[Int]
+ *
+ * Then v.m has symbol TermSymbol(flags = {OVERLOADED},
+ * tpe = OverloadedType(C[Int], List(m, m')))
+ * You recover the type of m doing a
+ *
+ * m.tpe.asSeenFrom(pre, C) (generally, owner of m, which is C here).
+ *
+ * or:
+ *
+ * pre.memberType(m)
+ */
+ final def newOverloaded(pre: Type, alternatives: List[Symbol]): Symbol =
+ newValue(alternatives.head.pos, alternatives.head.name.toTermName)
+ .setFlag(OVERLOADED)
+ .setInfo(OverloadedType(pre, alternatives))
+
+ /** for explicit outer phase */
+ final def newOuterAccessor(pos: Position) = {
+ val sym = newMethod(pos, nme.OUTER)
+ sym setFlag (STABLE | SYNTHETIC)
+ if (isTrait) sym setFlag DEFERRED
+ sym.expandName(this)
+ sym.referenced = this
+ sym
+ }
+
+ final def newErrorValue(name: TermName) =
+ newValue(pos, name).setFlag(SYNTHETIC | IS_ERROR).setInfo(ErrorType)
+
+ /** Symbol of a type definition type T = ...
+ */
+ final def newAliasType(pos: Position, name: TypeName) =
+ new TypeSymbol(this, pos, name)
+ final def newAliasType(name: TypeName, pos: Position = NoPosition) =
+ new TypeSymbol(this, pos, name)
+
+ /** Symbol of an abstract type type T >: ... <: ...
+ */
+ final def newAbstractType(pos: Position, name: TypeName) =
+ new TypeSymbol(this, pos, name).setFlag(DEFERRED)
+ final def newAbstractType(name: TypeName, pos: Position = NoPosition) =
+ new TypeSymbol(this, pos, name).setFlag(DEFERRED)
+
+ /** Symbol of a type parameter
+ */
+ final def newTypeParameter(pos: Position, name: TypeName) =
+ newAbstractType(pos, name).setFlag(PARAM)
+
+ /** Synthetic value parameters when parameter symbols are not available
+ */
+ final def newSyntheticValueParamss(argtypess: List[List[Type]]): List[List[Symbol]] = {
+ var cnt = 0
+ def freshName() = { cnt += 1; newTermName("x$" + cnt) }
+ def param(tp: Type) =
+ newValueParameter(focusPos(owner.pos), freshName()).setFlag(SYNTHETIC).setInfo(tp)
+ argtypess map (_.map(param))
+ }
+
+ final def newExistential(pos: Position, name: TypeName): Symbol =
+ newAbstractType(pos, name).setFlag(EXISTENTIAL)
+
+ final def freshExistential(suffix: String): Symbol =
+ newExistential(pos, freshExistentialName(suffix))
+
+ /** Synthetic value parameters when parameter symbols are not available.
+ * Calling this method multiple times will re-use the same parameter names.
+ */
+ final def newSyntheticValueParams(argtypes: List[Type]): List[Symbol] =
+ newSyntheticValueParamss(List(argtypes)).head
+
+ /** Synthetic value parameter when parameter symbol is not available.
+ * Calling this method multiple times will re-use the same parameter name.
+ */
+ final def newSyntheticValueParam(argtype: Type): Symbol =
+ newSyntheticValueParams(List(argtype)).head
+
+ /** Type skolems are type parameters ``seen from the inside''
+ * Assuming a polymorphic method m[T], its type is a PolyType which has a TypeParameter
+ * with name `T' in its typeParams list. While type checking the parameters, result type and
+ * body of the method, there's a local copy of `T' which is a TypeSkolem.
+ */
+ final def newTypeSkolem: Symbol =
+ new TypeSkolem(owner, pos, name.toTypeName, this)
+ .setFlag(flags)
+
+ final def newClass(pos: Position, name: TypeName) =
+ new ClassSymbol(this, pos, name)
+ final def newClass(name: TypeName, pos: Position = NoPosition) =
+ new ClassSymbol(this, pos, name)
+
+ final def newModuleClass(pos: Position, name: TypeName) =
+ new ModuleClassSymbol(this, pos, name)
+ final def newModuleClass(name: TypeName, pos: Position = NoPosition) =
+ new ModuleClassSymbol(this, pos, name)
+
+ final def newAnonymousClass(pos: Position) =
+ newClass(pos, tpnme.ANON_CLASS_NAME)
+ final def newAnonymousFunctionClass(pos: Position) =
+ newClass(pos, tpnme.ANON_FUN_NAME)
+
+ /** Refinement types P { val x: String; type T <: Number }
+ * also have symbols, they are refinementClasses
+ */
+ final def newRefinementClass(pos: Position) =
+ newClass(pos, tpnme.REFINE_CLASS_NAME)
+
+ /** Create a new getter for current symbol (which must be a field)
+ */
+ final def newGetter: Symbol = {
+ val getter = owner.newMethod(focusPos(pos), nme.getterName(name)).setFlag(getterFlags(flags))
+ getter.privateWithin = privateWithin
+ getter.setInfo(MethodType(List(), tpe))
+ }
+
+ final def newErrorClass(name: TypeName) = {
+ val clazz = newClass(pos, name).setFlag(SYNTHETIC | IS_ERROR)
+ clazz.setInfo(ClassInfoType(List(), new ErrorScope(this), clazz))
+ clazz
+ }
+
+ final def newErrorSymbol(name: Name): Symbol = name match {
+ case x: TypeName => newErrorClass(x)
+ case x: TermName => newErrorValue(x)
+ }
+
+// ----- locking and unlocking ------------------------------------------------------
+
+ // True if the symbol is unlocked.
+ // True if the symbol is locked but still below the allowed recursion depth.
+ // False otherwise
+ def lockOK: Boolean = {
+ ((rawflags & LOCKED) == 0L) ||
+ ((settings.Yrecursion.value != 0) &&
+ (recursionTable get this match {
+ case Some(n) => (n <= settings.Yrecursion.value)
+ case None => true }))
+ }
+
+ // Lock a symbol, using the handler if the recursion depth becomes too great.
+ def lock(handler: => Unit) = {
+ if ((rawflags & LOCKED) != 0L) {
+ if (settings.Yrecursion.value != 0) {
+ recursionTable get this match {
+ case Some(n) =>
+ if (n > settings.Yrecursion.value) {
+ handler
+ } else {
+ recursionTable += (this -> (n + 1))
+ }
+ case None =>
+ recursionTable += (this -> 1)
+ }
+ } else { handler }
+ } else {
+ rawflags |= LOCKED
+// activeLocks += 1
+// lockedSyms += this
+ }
+ }
+
+ // Unlock a symbol
+ def unlock() = {
+ if ((rawflags & LOCKED) != 0L) {
+// activeLocks -= 1
+// lockedSyms -= this
+ rawflags = rawflags & ~LOCKED
+ if (settings.Yrecursion.value != 0)
+ recursionTable -= this
+ }
+ }
+
+// ----- tests ----------------------------------------------------------------------
+
+ def isTerm = false // to be overridden
+ def isType = false // to be overridden
+ def isClass = false // to be overridden
+ def isAliasType = false // to be overridden
+ def isAbstractType = false // to be overridden
+ private[scala] def isSkolem = false // to be overridden
+
+ /** Is this symbol a type but not a class? */
+ def isNonClassType = false // to be overridden
+
+ override final def isTrait: Boolean = isClass && hasFlag(TRAIT | notDEFERRED) // A virtual class becomes a trait (part of DEVIRTUALIZE)
+ final def isAbstractClass = isClass && hasFlag(ABSTRACT)
+ final def isBridge = hasFlag(BRIDGE)
+ final def isContravariant = isType && hasFlag(CONTRAVARIANT)
+ final def isCovariant = isType && hasFlag(COVARIANT)
+ final def isEarlyInitialized: Boolean = isTerm && hasFlag(PRESUPER)
+ final def isExistentiallyBound = isType && hasFlag(EXISTENTIAL)
+ final def isImplClass = isClass && hasFlag(IMPLCLASS) // Is this symbol an implementation class for a mixin?
+ final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol
+ final def isMethod = isTerm && hasFlag(METHOD)
+ final def isVarargsMethod = isMethod && hasFlag(VARARGS)
+ final def isModule = isTerm && hasFlag(MODULE)
+ final def isModuleClass = isClass && hasFlag(MODULE)
+ final def isOverloaded = hasFlag(OVERLOADED)
+ final def isRefinementClass = isClass && name == tpnme.REFINE_CLASS_NAME
+ final def isSourceMethod = isMethod && !hasFlag(STABLE) // exclude all accessors!!!
+ final def isTypeParameter = isType && isParameter && !isSkolem
+
+ /** Package tests */
+ final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME
+ final def isEmptyPackageClass = isPackageClass && name == tpnme.EMPTY_PACKAGE_NAME
+ final def isPackage = isModule && hasFlag(PACKAGE)
+ final def isPackageClass = isClass && hasFlag(PACKAGE)
+ final def isRoot = isPackageClass && owner == NoSymbol
+ final def isRootPackage = isPackage && owner == NoSymbol
+
+ /** Does this symbol denote a wrapper created by the repl? */
+ final def isInterpreterWrapper = (isModule || isModuleClass) && nme.isReplWrapperName(name)
+
+ /** Is this symbol an effective root for fullname string?
+ */
+ def isEffectiveRoot = isRoot || isEmptyPackageClass || isInterpreterWrapper
+
+ /** Term symbols with the exception of static parts of Java classes and packages.
+ */
+ final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA))
+
+ final def isVariable = isTerm && isMutable && !isMethod
+
+ // interesting only for lambda lift. Captured variables are accessed from inner lambdas.
+ final def isCapturedVariable = isVariable && hasFlag(CAPTURED)
+
+ final def isGetter = isTerm && hasAccessorFlag && !nme.isSetterName(name)
+ // todo: make independent of name, as this can be forged.
+ final def isSetter = isTerm && hasAccessorFlag && nme.isSetterName(name)
+ def isSetterParameter = isValueParameter && owner.isSetter
+
+ final def hasGetter = isTerm && nme.isLocalName(name)
+
+ final def isValueParameter = isTerm && hasFlag(PARAM)
+ final def isLocalDummy = isTerm && nme.isLocalDummyName(name)
+ final def isInitializedToDefault = !isType && hasAllFlags(DEFAULTINIT | ACCESSOR)
+ final def isClassConstructor = isTerm && (name == nme.CONSTRUCTOR)
+ final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR)
+ final def isConstructor = isTerm && nme.isConstructorName(name)
+ final def isStaticModule = isModule && isStatic && !isMethod
+ final def isThisSym = isTerm && owner.thisSym == this
+ final def isError = hasFlag(IS_ERROR)
+ final def isErroneous = isError || isInitialized && tpe.isErroneous
+ final def isTypeParameterOrSkolem = isType && hasFlag(PARAM)
+ final def isHigherOrderTypeParameter = owner.isTypeParameterOrSkolem
+ final def isTypeSkolem = isSkolem && hasFlag(PARAM)
+ // a type symbol bound by an existential type, for instance the T in
+ // List[T] forSome { type T }
+ final def isExistentialSkolem = isExistentiallyBound && isSkolem
+ final def isExistentialQuantified = isExistentiallyBound && !isSkolem
+
+ // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor
+ final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
+
+ final def isAnonymousClass = isClass && (name containsName tpnme.ANON_CLASS_NAME)
+ final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME)
+ final def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass
+
+ final def isPackageObject = isModule && name == nme.PACKAGEkw && owner.isPackageClass
+ final def isPackageObjectClass = isModuleClass && name.toTermName == nme.PACKAGEkw && owner.isPackageClass
+ final def definedInPackage = owner.isPackageClass || owner.isPackageObjectClass
+ final def isJavaInterface = isJavaDefined && isTrait
+ final def needsFlatClasses: Boolean = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass
+
+ // not printed as prefixes
+ final def isPredefModule = this == PredefModule
+ final def isScalaPackage = (this == ScalaPackage) || (isPackageObject && owner == ScalaPackageClass)
+ final def isScalaPackageClass = skipPackageObject == ScalaPackageClass
+
+ /** If this is a package object or package object class, its owner: otherwise this.
+ */
+ final def skipPackageObject: Symbol = if (isPackageObjectClass) owner else this
+
+ /** If this is a constructor, its owner: otherwise this.
+ */
+ final def skipConstructor: Symbol = if (isConstructor) owner else this
+
+ /** Conditions where we omit the prefix when printing a symbol, to avoid
+ * unpleasantries like Predef.String, $iw.$iw.Foo and <empty>.Bippy.
+ */
+ final def printWithoutPrefix = !settings.debug.value && (
+ isScalaPackageClass || isPredefModule || isEffectiveRoot || isAnonOrRefinementClass || isInterpreterWrapper
+ )
+
+ /** Is symbol a monomorphic type?
+ * assumption: if a type starts out as monomorphic, it will not acquire
+ * type parameters in later phases.
+ */
+ final def isMonomorphicType =
+ isType && {
+ var is = infos
+ (is eq null) || {
+ while (is.prev ne null) { is = is.prev }
+ is.info.isComplete && is.info.typeParams.isEmpty
+ }
+ }
+
+ def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr)
+ def isSerializable = info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass) || hasAnnotation(SerializableAttr) // last part can be removed, @serializable annotation is deprecated
+ def isDeprecated = hasAnnotation(DeprecatedAttr)
+ def hasBridgeAnnotation = hasAnnotation(BridgeClass)
+ def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0)
+ def deprecationVersion = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 1)
+ // !!! when annotation arguments are not literal strings, but any sort of
+ // assembly of strings, there is a fair chance they will turn up here not as
+ // Literal(const) but some arbitrary AST. However nothing in the compiler
+ // prevents someone from writing a @migration annotation with a calculated
+ // string. So this needs attention. For now the fact that migration is
+ // private[scala] ought to provide enough protection.
+ def migrationMessage = getAnnotation(MigrationAnnotationClass) flatMap { _.stringArg(2) }
+ def elisionLevel = getAnnotation(ElidableMethodClass) flatMap { _.intArg(0) }
+ def implicitNotFoundMsg = getAnnotation(ImplicitNotFoundClass) flatMap { _.stringArg(0) }
+
+ /** Is this symbol an accessor method for outer? */
+ final def isOuterAccessor = {
+ hasFlag(STABLE | SYNTHETIC) &&
+ originalName == nme.OUTER
+ }
+
+ /** Is this symbol an accessor method for outer? */
+ final def isOuterField = {
+ hasFlag(SYNTHETIC) &&
+ originalName == nme.OUTER_LOCAL
+ }
+
+ /** Does this symbol denote a stable value? */
+ final def isStable =
+ isTerm &&
+ !isMutable &&
+ (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) &&
+ !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass))
+
+ def isVirtualClass =
+ hasFlag(DEFERRED) && isClass
+
+ def isVirtualTrait =
+ hasFlag(DEFERRED) && isTrait
+
+ def isLiftedMethod = isMethod && hasFlag(LIFTED)
+ def isCaseClass = isClass && isCase
+
+ /** Does this symbol denote the primary constructor of its enclosing class? */
+ final def isPrimaryConstructor =
+ isConstructor && owner.primaryConstructor == this
+
+ /** Does this symbol denote an auxiliary constructor of its enclosing class? */
+ final def isAuxiliaryConstructor =
+ isConstructor && !isPrimaryConstructor
+
+ /** Is this symbol a synthetic apply or unapply method in a companion object of a case class? */
+ final def isCaseApplyOrUnapply =
+ isMethod && isCase && isSynthetic
+
+ /** Is this symbol a trait which needs an implementation class? */
+ final def needsImplClass: Boolean =
+ isTrait && (!isInterface || hasFlag(lateINTERFACE)) && !isImplClass
+
+ /** Is this a symbol which exists only in the implementation class, not in its trait? */
+ final def isImplOnly: Boolean =
+ hasFlag(PRIVATE) ||
+ (owner.isImplClass || owner.isTrait) &&
+ ((hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR | MODULE) || isConstructor) ||
+ (hasFlag(LIFTED) && isModule && isMethod))
+
+ /** Is this symbol a module variable?
+ * This used to have to test for MUTABLE to distinguish the overloaded
+ * MODULEVAR/SYNTHETICMETH flag, but now SYNTHETICMETH is gone.
+ */
+ final def isModuleVar = hasFlag(MODULEVAR)
+
+ /** Is this symbol static (i.e. with no outer instance)? */
+ final def isStatic: Boolean =
+ hasFlag(STATIC) || isRoot || owner.isStaticOwner
+
+ /** Is this symbol a static constructor? */
+ final def isStaticConstructor: Boolean =
+ isStaticMember && isClassConstructor
+
+ /** Is this symbol a static member of its class? (i.e. needs to be implemented as a Java static?) */
+ final def isStaticMember: Boolean =
+ hasFlag(STATIC) || owner.isImplClass
+
+ /** Does this symbol denote a class that defines static symbols? */
+ final def isStaticOwner: Boolean =
+ isPackageClass || isModuleClass && isStatic
+
+ /** Is this symbol effectively final? I.e, it cannot be overridden */
+ final def isEffectivelyFinal: Boolean = isFinal || isTerm && (
+ hasFlag(PRIVATE) || isLocal || owner.isClass && owner.hasFlag(FINAL | MODULE))
+
+ /** Is this symbol locally defined? I.e. not accessed from outside `this' instance */
+ final def isLocal: Boolean = owner.isTerm
+
+ /** Is this symbol a constant? */
+ final def isConstant: Boolean =
+ isStable && (tpe match {
+ case ConstantType(_) => true
+ case PolyType(_, ConstantType(_)) => true
+ case MethodType(_, ConstantType(_)) => true
+ case NullaryMethodType(ConstantType(_)) => true
+ case _ => false
+ })
+
+ /** Is this class nested in another class or module (not a package)? */
+ final def isNestedClass: Boolean =
+ isClass && !isRoot && !owner.isPackageClass
+
+ /** Is this class locally defined?
+ * A class is local, if
+ * - it is anonymous, or
+ * - its owner is a value
+ * - it is defined within a local class
+ */
+ final def isLocalClass: Boolean =
+ isClass && (isAnonOrRefinementClass || isLocal ||
+ !owner.isPackageClass && owner.isLocalClass)
+
+/* code for fixing nested objects
+ override final def isModuleClass: Boolean =
+ super.isModuleClass && !isExpandedModuleClass
+*/
+ /** Is this class or type defined as a structural refinement type?
+ */
+ final def isStructuralRefinement: Boolean =
+ (isClass || isType || isModule) && info.normalize/*.underlying*/.isStructuralRefinement
+
+
+ /** Is this symbol a member of class `clazz'
+ */
+ def isMemberOf(clazz: Symbol) =
+ clazz.info.member(name).alternatives contains this
+
+ /** A a member of class `base' is incomplete if
+ * (1) it is declared deferred or
+ * (2) it is abstract override and its super symbol in `base' is
+ * nonexistent or incomplete.
+ *
+ * @param base ...
+ * @return ...
+ */
+ final def isIncompleteIn(base: Symbol): Boolean =
+ this.isDeferred ||
+ (this hasFlag ABSOVERRIDE) && {
+ val supersym = superSymbol(base)
+ supersym == NoSymbol || supersym.isIncompleteIn(base)
+ }
+
+ // Does not always work if the rawInfo is a SourcefileLoader, see comment
+ // in "def coreClassesFirst" in Global.
+ final def exists: Boolean =
+ this != NoSymbol && (!owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType })
+
+ final def isInitialized: Boolean =
+ validTo != NoPeriod
+
+ final def isStableClass: Boolean = {
+ def hasNoAbstractTypeMember(clazz: Symbol): Boolean =
+ (clazz hasFlag STABLE) || {
+ var e = clazz.info.decls.elems
+ while ((e ne null) && !(e.sym.isAbstractType && info.member(e.sym.name) == e.sym))
+ e = e.next
+ e == null
+ }
+ def checkStable() =
+ (info.baseClasses forall hasNoAbstractTypeMember) && { setFlag(STABLE); true }
+ isClass && (hasFlag(STABLE) || checkStable())
+ }
+
+
+ /** The variance of this symbol as an integer */
+ final def variance: Int =
+ if (isCovariant) 1
+ else if (isContravariant) -1
+ else 0
+
+// ------ owner attribute --------------------------------------------------------------
+
+ def owner: Symbol = rawowner
+ final def owner_=(owner: Symbol) {
+ if (originalOwner contains this) ()
+ else originalOwner(this) = rawowner
+
+ rawowner = owner
+ }
+ private[Symbols] def flattenName(): Name = {
+ // TODO: this assertion causes me a lot of trouble in the interpeter in situations
+ // where everything proceeds smoothly if there's no assert. I don't think calling "name"
+ // on a symbol is the right place to throw fatal exceptions if things don't look right.
+ // It really hampers exploration.
+ assert(rawowner.isClass, "fatal: %s has non-class owner %s after flatten.".format(rawname + idString, rawowner))
+ nme.flattenedName(rawowner.name, rawname)
+ }
+
+ def ownerChain: List[Symbol] = this :: owner.ownerChain
+ def enclClassChain: List[Symbol] = {
+ if (this eq NoSymbol) Nil
+ else if (isClass && !isPackageClass) this :: owner.enclClassChain
+ else owner.enclClassChain
+ }
+
+ def ownersIterator: Iterator[Symbol] = new Iterator[Symbol] {
+ private var current = Symbol.this
+ def hasNext = current ne NoSymbol
+ def next = { val r = current; current = current.owner; r }
+ }
+
+ /** same as ownerChain contains sym, but more efficient, and
+ * with a twist for refinement classes. A refinement class
+ * has a transowner X if an of its parents has transowner X.
+ */
+ def hasTransOwner(sym: Symbol): Boolean = {
+ var o = this
+ while ((o ne sym) && (o ne NoSymbol)) o = o.owner
+ (o eq sym) ||
+ isRefinementClass && (info.parents exists (_.typeSymbol.hasTransOwner(sym)))
+ }
+
+// ------ name attribute --------------------------------------------------------------
+
+ def name: Name = rawname
+
+ final def name_=(name: Name) {
+ if (name != rawname) {
+ if (owner.isClass) {
+ var ifs = owner.infos
+ while (ifs != null) {
+ ifs.info.decls.rehash(this, name)
+ ifs = ifs.prev
+ }
+ }
+ rawname = name
+ }
+ }
+
+ /** If this symbol has an expanded name, its original name, otherwise its name itself.
+ * @see expandName
+ */
+ def originalName = nme.originalName(name)
+
+ /** The name of the symbol before decoding, e.g. `\$eq\$eq` instead of `==`.
+ */
+ def encodedName: String = name.toString
+
+ /** The decoded name of the symbol, e.g. `==` instead of `\$eq\$eq`.
+ */
+ def decodedName: String = stripLocalSuffix(NameTransformer.decode(encodedName))
+
+ /** The encoded full path name of this symbol, where outer names and inner names
+ * are separated by `separator` characters.
+ * Never translates expansions of operators back to operator symbol.
+ * Never adds id.
+ */
+ final def fullName(separator: Char): String = stripLocalSuffix {
+ if (isRoot || isRootPackage || this == NoSymbol) this.toString
+ else if (owner.isEffectiveRoot) encodedName
+ else owner.enclClass.fullName(separator) + separator + encodedName
+ }
+
+ private def stripLocalSuffix(s: String) = s stripSuffix nme.LOCAL_SUFFIX_STRING
+
+ /** The encoded full path name of this symbol, where outer names and inner names
+ * are separated by periods.
+ */
+ final def fullName: String = fullName('.')
+
+// ------ flags attribute --------------------------------------------------------------
+
+ final def flags: Long = {
+ val fs = rawflags & phase.flagMask
+ (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift)
+ }
+ final def flags_=(fs: Long) = rawflags = fs
+ final def setFlag(mask: Long): this.type = { rawflags = rawflags | mask; this }
+ final def resetFlag(mask: Long): this.type = { rawflags = rawflags & ~mask; this }
+ final def getFlag(mask: Long): Long = flags & mask
+ final def resetFlags { rawflags = rawflags & TopLevelCreationFlags }
+
+ /** Does symbol have ANY flag in `mask` set? */
+ final def hasFlag(mask: Long): Boolean = (flags & mask) != 0L
+
+ /** Does symbol have ALL the flags in `mask` set? */
+ final def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask
+
+ /** The class or term up to which this symbol is accessible,
+ * or RootClass if it is public.
+ */
+ def accessBoundary(base: Symbol): Symbol = {
+ if (hasFlag(PRIVATE) || isLocal) owner
+ else if (hasAccessBoundary && !phase.erasedTypes) privateWithin
+ else if (hasFlag(PROTECTED)) base
+ else RootClass
+ }
+
+ def isLessAccessibleThan(other: Symbol): Boolean = {
+ val tb = this.accessBoundary(owner)
+ val ob1 = other.accessBoundary(owner)
+ val ob2 = ob1.linkedClassOfClass
+ var o = tb
+ while (o != NoSymbol && o != ob1 && o != ob2) {
+ o = o.owner
+ }
+ o != NoSymbol && o != tb
+ }
+
+ /** See comment in HasFlags for how privateWithin combines with flags.
+ */
+ private[this] var _privateWithin: Symbol = _
+ def privateWithin = _privateWithin
+ def privateWithin_=(sym: Symbol) { _privateWithin = sym }
+
+ /** Does symbol have a private or protected qualifier set? */
+ final def hasAccessBoundary = (privateWithin != null) && (privateWithin != NoSymbol)
+
+// ------ info and type -------------------------------------------------------------------
+
+ private[Symbols] var infos: TypeHistory = null
+
+ /** Get type. The type of a symbol is:
+ * for a type symbol, the type corresponding to the symbol itself,
+ * @M you should use tpeHK for a type symbol with type parameters if
+ * the kind of the type need not be *, as tpe introduces dummy arguments
+ * to generate a type of kind *
+ * for a term symbol, its usual type
+ */
+ def tpe: Type = info
+
+ /** Get type info associated with symbol at current phase, after
+ * ensuring that symbol is initialized (i.e. type is completed).
+ */
+ def info: Type = try {
+ var cnt = 0
+ while (validTo == NoPeriod) {
+ //if (settings.debug.value) System.out.println("completing " + this);//DEBUG
+ assert(infos ne null, this.name)
+ assert(infos.prev eq null, this.name)
+ val tp = infos.info
+ //if (settings.debug.value) System.out.println("completing " + this.rawname + tp.getClass());//debug
+
+ if ((rawflags & LOCKED) != 0L) { // rolled out once for performance
+ lock {
+ setInfo(ErrorType)
+ throw CyclicReference(this, tp)
+ }
+ } else {
+ rawflags |= LOCKED
+// activeLocks += 1
+ // lockedSyms += this
+ }
+ val current = phase
+ try {
+ phase = phaseOf(infos.validFrom)
+ tp.complete(this)
+ } finally {
+ unlock()
+ phase = current
+ }
+ cnt += 1
+ // allow for two completions:
+ // one: sourceCompleter to LazyType, two: LazyType to completed type
+ if (cnt == 3) abort("no progress in completing " + this + ":" + tp)
+ }
+ val result = rawInfo
+ result
+ } catch {
+ case ex: CyclicReference =>
+ if (settings.debug.value) println("... trying to complete "+this)
+ throw ex
+ }
+
+ def info_=(info: Type) {
+ assert(info ne null)
+ infos = TypeHistory(currentPeriod, info, null)
+ unlock()
+ validTo = if (info.isComplete) currentPeriod else NoPeriod
+ }
+
+ /** Set initial info. */
+ def setInfo(info: Type): this.type = { info_=(info); this }
+
+ def setInfoOwnerAdjusted(info: Type): this.type = setInfo(info.atOwner(this))
+
+ /** Set new info valid from start of this phase. */
+ final def updateInfo(info: Type): Symbol = {
+ assert(phaseId(infos.validFrom) <= phase.id)
+ if (phaseId(infos.validFrom) == phase.id) infos = infos.prev
+ infos = TypeHistory(currentPeriod, info, infos)
+ validTo = if (info.isComplete) currentPeriod else NoPeriod
+ this
+ }
+
+ def hasRawInfo: Boolean = infos ne null
+
+ /** Return info without checking for initialization or completing */
+ def rawInfo: Type = {
+ var infos = this.infos
+ assert(infos != null)
+ val curPeriod = currentPeriod
+ val curPid = phaseId(curPeriod)
+
+ if (validTo != NoPeriod) {
+ // skip any infos that concern later phases
+ while (curPid < phaseId(infos.validFrom) && infos.prev != null)
+ infos = infos.prev
+
+ if (validTo < curPeriod) {
+ // adapt any infos that come from previous runs
+ val current = phase
+ try {
+ infos = adaptInfos(infos)
+
+ //assert(runId(validTo) == currentRunId, name)
+ //assert(runId(infos.validFrom) == currentRunId, name)
+
+ if (validTo < curPeriod) {
+ var itr = infoTransformers.nextFrom(phaseId(validTo))
+ infoTransformers = itr; // caching optimization
+ while (itr.pid != NoPhase.id && itr.pid < current.id) {
+ phase = phaseWithId(itr.pid)
+ val info1 = itr.transform(this, infos.info)
+ if (info1 ne infos.info) {
+ infos = TypeHistory(currentPeriod + 1, info1, infos)
+ this.infos = infos
+ }
+ validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform
+ itr = itr.next
+ }
+ validTo = if (itr.pid == NoPhase.id) curPeriod
+ else period(currentRunId, itr.pid)
+ }
+ } finally {
+ phase = current
+ }
+ }
+ }
+ infos.info
+ }
+
+ // adapt to new run in fsc.
+ private def adaptInfos(infos: TypeHistory): TypeHistory =
+ if (infos == null || runId(infos.validFrom) == currentRunId) {
+ infos
+ } else {
+ val prev1 = adaptInfos(infos.prev)
+ if (prev1 ne infos.prev) prev1
+ else {
+ def adaptToNewRun(info: Type): Type =
+ if (isPackageClass) info else adaptToNewRunMap(info)
+ val pid = phaseId(infos.validFrom)
+ validTo = period(currentRunId, pid)
+ phase = phaseWithId(pid)
+ val info1 = adaptToNewRun(infos.info)
+ if (info1 eq infos.info) {
+ infos.validFrom = validTo
+ infos
+ } else {
+ this.infos = TypeHistory(validTo, info1, prev1)
+ this.infos
+ }
+ }
+ }
+
+ /** Initialize the symbol */
+ final def initialize: this.type = {
+ if (!isInitialized) info
+ this
+ }
+
+ /** Was symbol's type updated during given phase? */
+ final def isUpdatedAt(pid: Phase#Id): Boolean = {
+ var infos = this.infos
+ while ((infos ne null) && phaseId(infos.validFrom) != pid + 1) infos = infos.prev
+ infos ne null
+ }
+
+ /** Was symbol's type updated during given phase? */
+ final def hasTypeAt(pid: Phase#Id): Boolean = {
+ var infos = this.infos
+ while ((infos ne null) && phaseId(infos.validFrom) > pid) infos = infos.prev
+ infos ne null
+ }
+
+ /** Modify term symbol's type so that a raw type C is converted to an existential C[_]
+ *
+ * This is done in checkAccessible and overriding checks in refchecks
+ * We can't do this on class loading because it would result in infinite cycles.
+ */
+ final def cookJavaRawInfo() {
+ if (hasFlag(TRIEDCOOKING)) return else setFlag(TRIEDCOOKING) // only try once...
+ val oldInfo = info
+ doCookJavaRawInfo()
+ }
+
+ protected def doCookJavaRawInfo(): Unit
+
+
+ /** The type constructor of a symbol is:
+ * For a type symbol, the type corresponding to the symbol itself,
+ * excluding parameters.
+ * Not applicable for term symbols.
+ */
+ def typeConstructor: Type =
+ abort("typeConstructor inapplicable for " + this)
+
+ /** @M -- tpe vs tpeHK:
+ * Symbol::tpe creates a TypeRef that has dummy type arguments to get a type of kind *
+ * Symbol::tpeHK creates a TypeRef without type arguments, but with type params --> higher-kinded if non-empty list of tpars
+ * calling tpe may hide errors or introduce spurious ones
+ * (e.g., when deriving a type from the symbol of a type argument that must be higher-kinded)
+ * as far as I can tell, it only makes sense to call tpe in conjunction with a substitution that replaces the generated dummy type arguments by their actual types
+ */
+ def tpeHK = if (isType) typeConstructor else tpe // @M! used in memberType
+
+ /** The type parameters of this symbol, without ensuring type completion.
+ * assumption: if a type starts out as monomorphic, it will not acquire
+ * type parameters later.
+ */
+ def unsafeTypeParams: List[Symbol] =
+ if (isMonomorphicType) List()
+ else {
+ val current = phase
+ try {
+ while ((phase.prev ne NoPhase) && phase.prev.keepsTypeParams) phase = phase.prev
+ if (phase ne current) phase = phase.next
+ if (settings.debug.value && settings.verbose.value && (phase ne current))
+ log("checking unsafeTypeParams(" + this + ") at: " + current + " reading at: " + phase)
+ rawInfo.typeParams
+ } finally {
+ phase = current
+ }
+ }
+
+ /** The type parameters of this symbol.
+ * assumption: if a type starts out as monomorphic, it will not acquire
+ * type parameters later.
+ */
+ def typeParams: List[Symbol] =
+ if (isMonomorphicType)
+ List()
+ else {
+ if (validTo == NoPeriod) {
+ val current = phase
+ try {
+ phase = phaseOf(infos.validFrom)
+ rawInfo.load(this)
+ } finally {
+ phase = current
+ }
+ }
+ rawInfo.typeParams
+ }
+
+ /** The value parameter sections of this symbol.
+ */
+ def paramss: List[List[Symbol]] = info.paramss
+ def hasParamWhich(cond: Symbol => Boolean) = paramss exists (_ exists cond)
+
+ /** The least proper supertype of a class; includes all parent types
+ * and refinement where needed. You need to compute that in a situation like this:
+ * {
+ * class C extends P { ... }
+ * new C
+ * }
+ */
+ def classBound: Type = {
+ val tp = refinedType(info.parents, owner)
+ val thistp = tp.typeSymbol.thisType
+ val oldsymbuf = new ListBuffer[Symbol]
+ val newsymbuf = new ListBuffer[Symbol]
+ for (sym <- info.decls.toList) {
+ // todo: what about public references to private symbols?
+ if (sym.isPublic && !sym.isConstructor) {
+ oldsymbuf += sym
+ newsymbuf += (
+ if (sym.isClass)
+ tp.typeSymbol.newAbstractType(sym.pos, sym.name.toTypeName).setInfo(sym.existentialBound)
+ else
+ sym.cloneSymbol(tp.typeSymbol))
+ }
+ }
+ val oldsyms = oldsymbuf.toList
+ val newsyms = newsymbuf.toList
+ for (sym <- newsyms) {
+ addMember(thistp, tp, sym.setInfo(sym.info.substThis(this, thistp).substSym(oldsyms, newsyms)))
+ }
+ tp
+ }
+
+ /** If we quantify existentially over this symbol,
+ * the bound of the type variable that stands for it
+ * pre: symbol is a term, a class, or an abstract type (no alias type allowed)
+ */
+ def existentialBound: Type =
+ if (this.isClass)
+ polyType(this.typeParams, TypeBounds.upper(this.classBound))
+ else if (this.isAbstractType)
+ this.info
+ else if (this.isTerm)
+ TypeBounds.upper(intersectionType(List(this.tpe, SingletonClass.tpe)))
+ else
+ abort("unexpected alias type: "+this)
+
+ /** Reset symbol to initial state
+ */
+ def reset(completer: Type) {
+ resetFlags
+ infos = null
+ validTo = NoPeriod
+ //limit = NoPhase.id
+ setInfo(completer)
+ }
+
+ /**
+ * Adds the interface scala.Serializable to the parents of a ClassInfoType.
+ * Note that the tree also has to be updated accordingly.
+ */
+ def makeSerializable() {
+ info match {
+ case ci @ ClassInfoType(_, _, _) =>
+ updateInfo(ci.copy(parents = ci.parents ::: List(SerializableClass.tpe)))
+ case i =>
+ abort("Only ClassInfoTypes can be made serializable: "+ i)
+ }
+ }
+
+// ----- setters implemented in selected subclasses -------------------------------------
+
+ def typeOfThis_=(tp: Type) { throw new UnsupportedOperationException("typeOfThis_= inapplicable for " + this) }
+ def sourceModule_=(sym: Symbol) { throw new UnsupportedOperationException("sourceModule_= inapplicable for " + this) }
+ def addChild(sym: Symbol) { throw new UnsupportedOperationException("addChild inapplicable for " + this) }
+
+// ----- annotations ------------------------------------------------------------
+
+ private var rawannots: List[AnnotationInfoBase] = Nil
+ def rawAnnotations = rawannots
+
+ /* Used in namer to check whether annotations were already assigned or not */
+ def hasAssignedAnnotations = rawannots.nonEmpty
+
+ /** After the typer phase (before, look at the definition's Modifiers), contains
+ * the annotations attached to member a definition (class, method, type, field).
+ */
+ def annotations: List[AnnotationInfo] = {
+ // .initialize: the type completer of the symbol parses the annotations,
+ // see "def typeSig" in Namers
+ val annots1 = initialize.rawannots map {
+ case x: LazyAnnotationInfo => x.annot()
+ case x: AnnotationInfo => x
+ } filterNot (_.atp.isError)
+ rawannots = annots1
+ annots1
+ }
+
+ def setAnnotations(annots: List[AnnotationInfoBase]): this.type = {
+ this.rawannots = annots
+ this
+ }
+
+ def addAnnotation(annot: AnnotationInfo) {
+ setAnnotations(annot :: this.rawannots)
+ }
+
+ /** Does this symbol have an annotation of the given class? */
+ def hasAnnotation(cls: Symbol) =
+ getAnnotation(cls).isDefined
+
+ def getAnnotation(cls: Symbol): Option[AnnotationInfo] =
+ annotations find (_.atp.typeSymbol == cls)
+
+ /** Remove all annotations matching the given class. */
+ def removeAnnotation(cls: Symbol): Unit =
+ setAnnotations(annotations filterNot (_.atp.typeSymbol == cls))
+
+// ------ comparisons ----------------------------------------------------------------
+
+ /** A total ordering between symbols that refines the class
+ * inheritance graph (i.e. subclass.isLess(superclass) always holds).
+ * the ordering is given by: (_.isType, -_.baseTypeSeq.length) for type symbols, followed by `id'.
+ */
+ final def isLess(that: Symbol): Boolean = {
+ def baseTypeSeqLength(sym: Symbol) =
+ if (sym.isAbstractType) 1 + sym.info.bounds.hi.baseTypeSeq.length
+ else sym.info.baseTypeSeq.length
+ if (this.isType)
+ (that.isType &&
+ { val diff = baseTypeSeqLength(this) - baseTypeSeqLength(that)
+ diff > 0 || diff == 0 && this.id < that.id })
+ else
+ that.isType || this.id < that.id
+ }
+
+ /** A partial ordering between symbols.
+ * (this isNestedIn that) holds iff this symbol is defined within
+ * a class or method defining that symbol
+ */
+ final def isNestedIn(that: Symbol): Boolean =
+ owner == that || owner != NoSymbol && (owner isNestedIn that)
+
+ /** Is this class symbol a subclass of that symbol? */
+ final def isNonBottomSubClass(that: Symbol): Boolean =
+ this == that || this.isError || that.isError ||
+ info.baseTypeIndex(that) >= 0
+
+ final def isSubClass(that: Symbol): Boolean = {
+ isNonBottomSubClass(that) ||
+ this == NothingClass ||
+ this == NullClass &&
+ (that == AnyClass ||
+ that != NothingClass && (that isSubClass AnyRefClass))
+ }
+ final def isNumericSubClass(that: Symbol): Boolean =
+ definitions.isNumericSubClass(this, that)
+
+// ------ overloaded alternatives ------------------------------------------------------
+
+ def alternatives: List[Symbol] =
+ if (hasFlag(OVERLOADED)) info.asInstanceOf[OverloadedType].alternatives
+ else List(this)
+
+ def filter(cond: Symbol => Boolean): Symbol =
+ if (hasFlag(OVERLOADED)) {
+ //assert(info.isInstanceOf[OverloadedType], "" + this + ":" + info);//DEBUG
+ val alts = alternatives
+ val alts1 = alts filter cond
+ if (alts1 eq alts) this
+ else if (alts1.isEmpty) NoSymbol
+ else if (alts1.tail.isEmpty) alts1.head
+ else owner.newOverloaded(info.prefix, alts1)
+ } else if (this == NoSymbol || cond(this)) {
+ this
+ } else NoSymbol
+
+ def suchThat(cond: Symbol => Boolean): Symbol = {
+ val result = filter(cond)
+ assert(!(result hasFlag OVERLOADED), result.alternatives)
+ result
+ }
+
+// ------ cloneing -------------------------------------------------------------------
+
+ /** A clone of this symbol */
+ final def cloneSymbol: Symbol =
+ cloneSymbol(owner)
+
+ /** A clone of this symbol, but with given owner */
+ final def cloneSymbol(owner: Symbol): Symbol = {
+ val newSym = cloneSymbolImpl(owner)
+ newSym.privateWithin = privateWithin
+ newSym.setInfo(info.cloneInfo(newSym))
+ .setFlag(this.rawflags).setAnnotations(this.annotations)
+ }
+
+ /** Internal method to clone a symbol's implementation without flags or type
+ */
+ def cloneSymbolImpl(owner: Symbol): Symbol
+
+// ------ access to related symbols --------------------------------------------------
+
+ /** The next enclosing class */
+ def enclClass: Symbol = if (isClass) this else owner.enclClass
+
+ /** The next enclosing method */
+ def enclMethod: Symbol = if (isSourceMethod) this else owner.enclMethod
+
+ /** The primary constructor of a class */
+ def primaryConstructor: Symbol = {
+ var c = info.decl(
+ if (isTrait || isImplClass) nme.MIXIN_CONSTRUCTOR
+ else nme.CONSTRUCTOR)
+ c = if (c hasFlag OVERLOADED) c.alternatives.head else c
+ //assert(c != NoSymbol)
+ c
+ }
+
+ /** The self symbol of a class with explicit self type, or else the
+ * symbol itself.
+ */
+ def thisSym: Symbol = this
+
+ /** The type of `this' in a class, or else the type of the symbol itself. */
+ def typeOfThis = thisSym.tpe
+
+ /** If symbol is a class, the type <code>this.type</code> in this class,
+ * otherwise <code>NoPrefix</code>.
+ * We always have: thisType <:< typeOfThis
+ */
+ def thisType: Type = NoPrefix
+
+ /** Return every accessor of a primary constructor parameter in this case class.
+ * The scope declarations may be out of order because fields with less than private
+ * access are first given a regular getter, then a new renamed getter which comes
+ * later in the declaration list. For this reason we have to pinpoint the
+ * right accessors by starting with the original fields (which will be in the right
+ * order) and looking for getters with applicable names. The getters may have the
+ * standard name "foo" or may have been renamed to "foo$\d+" in SyntheticMethods.
+ * See ticket #1373.
+ */
+ final def caseFieldAccessors: List[Symbol] = {
+ val allWithFlag = info.decls.toList filter (_.isCaseAccessor)
+ val (accessors, fields) = allWithFlag partition (_.isMethod)
+
+ def findAccessor(field: Symbol): Symbol = {
+ // There is another renaming the field may have undergone, for instance as in
+ // ticket #2175: case class Property[T](private var t: T), t becomes Property$$t.
+ // So we use the original name everywhere.
+ val getterName = nme.getterName(field.originalName)
+
+ // Note this is done in two passes intentionally, to ensure we pick up the original
+ // getter if present before looking for the renamed getter.
+ def origGetter = accessors find (_.originalName == getterName)
+ def renamedGetter = accessors find (_.originalName startsWith (getterName + "$"))
+ val accessorName = origGetter orElse renamedGetter
+
+ // This fails more gracefully rather than throw an Error as it used to because
+ // as seen in #2625, we can reach this point with an already erroneous tree.
+ accessorName getOrElse NoSymbol
+ // throw new Error("Could not find case accessor for %s in %s".format(field, this))
+ }
+
+ fields map findAccessor
+ }
+
+ final def constrParamAccessors: List[Symbol] =
+ info.decls.toList filter (sym => !sym.isMethod && sym.isParamAccessor)
+
+ /** The symbol accessed by this accessor (getter or setter) function. */
+ final def accessed: Symbol = accessed(owner.info)
+
+ /** The symbol accessed by this accessor function, but with given owner type */
+ final def accessed(ownerTp: Type): Symbol = {
+ assert(hasAccessorFlag)
+ ownerTp.decl(nme.getterToLocal(if (isSetter) nme.setterToGetter(name) else name))
+ }
+
+ /** The module corresponding to this module class (note that this
+ * is not updated when a module is cloned), or NoSymbol if this is not a ModuleClass
+ */
+ def sourceModule: Symbol = NoSymbol
+
+ /** The implementation class of a trait */
+ final def implClass: Symbol = owner.info.decl(nme.implClassName(name))
+
+ /** The class that is logically an outer class of given `clazz'.
+ * This is the enclosing class, except for classes defined locally to constructors,
+ * where it is the outer class of the enclosing class
+ */
+ final def outerClass: Symbol =
+ if (owner.isClass) owner
+ else if (isClassLocalToConstructor) owner.enclClass.outerClass
+ else owner.outerClass
+
+ /** For a paramaccessor: a superclass paramaccessor for which this symbol
+ * is an alias, NoSymbol for all others
+ */
+ def alias: Symbol = NoSymbol
+
+ /** For a lazy value, its lazy accessor. NoSymbol for all others */
+ def lazyAccessor: Symbol = NoSymbol
+
+ /** If this is a lazy value, the lazy accessor; otherwise this symbol. */
+ def lazyAccessorOrSelf: Symbol = if (isLazy) lazyAccessor else this
+
+ /** For an outer accessor: The class from which the outer originates.
+ * For all other symbols: NoSymbol
+ */
+ def outerSource: Symbol = NoSymbol
+
+ /** The superclass of this class */
+ def superClass: Symbol = if (info.parents.isEmpty) NoSymbol else info.parents.head.typeSymbol
+
+ /** The directly or indirectly inherited mixins of this class
+ * except for mixin classes inherited by the superclass. Mixin classes appear
+ * in linearization order.
+ */
+ def mixinClasses: List[Symbol] = {
+ val sc = superClass
+ ancestors takeWhile (sc ne)
+ }
+
+ /** All directly or indirectly inherited classes.
+ */
+ def ancestors: List[Symbol] = info.baseClasses drop 1
+
+ /** The package class containing this symbol, or NoSymbol if there
+ * is not one. */
+ def enclosingPackageClass: Symbol =
+ if (this == NoSymbol) this else {
+ var packSym = this.owner
+ while (packSym != NoSymbol && !packSym.isPackageClass)
+ packSym = packSym.owner
+ packSym
+ }
+
+ /** The package containing this symbol, or NoSymbol if there
+ * is not one. */
+ def enclosingPackage: Symbol = {
+ val packSym = enclosingPackageClass
+ if (packSym != NoSymbol) packSym.companionModule
+ else packSym
+ }
+
+ /** Return the original enclosing method of this symbol. It should return
+ * the same thing as enclMethod when called before lambda lift,
+ * but it preserves the original nesting when called afterwards.
+ */
+ def originalEnclosingMethod: Symbol = {
+ if (isMethod) this
+ else {
+ val owner = originalOwner.getOrElse(this, rawowner)
+ if (isLocalDummy) owner.enclClass.primaryConstructor
+ else owner.originalEnclosingMethod
+ }
+ }
+
+ /** The method or class which logically encloses the current symbol.
+ * If the symbol is defined in the initialization part of a template
+ * this is the template's primary constructor, otherwise it is
+ * the physically enclosing method or class.
+ *
+ * Example 1:
+ *
+ * def f() { val x = { def g() = ...; g() } }
+ *
+ * In this case the owner chain of `g' is `x', followed by `f' and
+ * `g.logicallyEnclosingMember == f`.
+ *
+ * Example 2:
+ *
+ * class C {
+ * def <init> = { ... }
+ * val x = { def g() = ...; g() } }
+ * }
+ *
+ * In this case the owner chain of `g' is `x', followed by `C' but
+ * g.logicallyEnclosingMember is the primary constructor symbol `<init>'
+ * (or, for traits: `$init') of `C'.
+ *
+ */
+ def logicallyEnclosingMember: Symbol =
+ if (isLocalDummy) enclClass.primaryConstructor
+ else if (isMethod || isClass) this
+ else owner.logicallyEnclosingMember
+
+ /** The top-level class containing this symbol */
+ def toplevelClass: Symbol =
+ if (owner.isPackageClass) {
+ if (isClass) this else moduleClass
+ } else owner.toplevelClass
+
+ /** Is this symbol defined in the same scope and compilation unit as `that' symbol?
+ */
+ def isCoDefinedWith(that: Symbol) = (
+ (this.rawInfo ne NoType) &&
+ (this.owner == that.owner) && {
+ !this.owner.isPackageClass ||
+ (this.sourceFile eq null) ||
+ (that.sourceFile eq null) ||
+ (this.sourceFile == that.sourceFile) || {
+ // recognize companion object in separate file and fail, else compilation
+ // appears to succeed but highly opaque errors come later: see bug #1286
+ if (this.sourceFile.path != that.sourceFile.path)
+ throw InvalidCompanions(this, that)
+
+ false
+ }
+ }
+ )
+
+ /** The internal representation of classes and objects:
+ *
+ * class Foo is "the class" or sometimes "the plain class"
+ * object Foo is "the module"
+ * class Foo$ is "the module class" (invisible to the user: it implements object Foo)
+ *
+ * class Foo <
+ * ^ ^ (2) \
+ * | | | \
+ * | (5) | (3)
+ * | | | \
+ * (1) v v \
+ * object Foo (4)-> > class Foo$
+ *
+ * (1) companionClass
+ * (2) companionModule
+ * (3) linkedClassOfClass
+ * (4) moduleClass
+ * (5) companionSymbol
+ */
+
+ /** For a module or case factory: the class with the same name in the same package.
+ * For all others: NoSymbol
+ * Note: does not work for classes owned by methods, see Namers.companionClassOf
+ *
+ * object Foo . companionClass --> class Foo
+ */
+ final def companionClass: Symbol = {
+ if (this != NoSymbol)
+ flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this)
+ else NoSymbol
+ }
+
+ /** A helper method that factors the common code used the discover a
+ * companion module of a class. If a companion module exists, its symbol is
+ * returned, otherwise, `NoSymbol` is returned. The method assumes that
+ * `this` symbol has already been checked to be a class (using `isClass`).
+ */
+ private final def companionModule0: Symbol =
+ flatOwnerInfo.decl(name.toTermName).suchThat(
+ sym => sym.hasFlag(MODULE) && (sym isCoDefinedWith this) && !sym.isMethod)
+
+ /** For a class: the module or case class factory with the same name in the same package.
+ * For all others: NoSymbol
+ * Note: does not work for modules owned by methods, see Namers.companionModuleOf
+ *
+ * class Foo . companionModule --> object Foo
+ */
+ final def companionModule: Symbol =
+ if (isClass && !isRefinementClass) companionModule0
+ else NoSymbol
+
+ /** For a module: its linked class
+ * For a plain class: its linked module or case factory.
+ * Note: does not work for modules owned by methods, see Namers.companionSymbolOf
+ *
+ * class Foo <-- companionSymbol --> object Foo
+ */
+ final def companionSymbol: Symbol =
+ if (isTerm) companionClass
+ else if (isClass) companionModule0
+ else NoSymbol
+
+ /** For a module class: its linked class
+ * For a plain class: the module class of its linked module.
+ *
+ * class Foo <-- linkedClassOfClass --> class Foo$
+ */
+ final def linkedClassOfClass: Symbol =
+ if (isModuleClass) companionClass else companionModule.moduleClass
+
+ /**
+ * Returns the rawInfo of the owner. If the current phase has flat classes,
+ * it first applies all pending type maps to this symbol.
+ *
+ * assume this is the ModuleSymbol for B in the following definition:
+ * package p { class A { object B { val x = 1 } } }
+ *
+ * The owner after flatten is "package p" (see "def owner"). The flatten type map enters
+ * symbol B in the decls of p. So to find a linked symbol ("object B" or "class B")
+ * we need to apply flatten to B first. Fixes #2470.
+ */
+ private final def flatOwnerInfo: Type = {
+ if (needsFlatClasses)
+ info
+ owner.rawInfo
+ }
+
+ /** If this symbol is an implementation class, its interface, otherwise the symbol itself
+ * The method follows two strategies to determine the interface.
+ * - during or after erasure, it takes the last parent of the implementation class
+ * (which is always the interface, by convention)
+ * - before erasure, it looks up the interface name in the scope of the owner of the class.
+ * This only works for implementation classes owned by other classes or traits.
+ */
+ final def toInterface: Symbol =
+ if (isImplClass) {
+ val result =
+ if (phase.next.erasedTypes) {
+ assert(!tpe.parents.isEmpty, this)
+ tpe.parents.last.typeSymbol
+ } else {
+ owner.info.decl(nme.interfaceName(name))
+ }
+ assert(result != NoSymbol, this)
+ result
+ } else this
+
+ /** The module class corresponding to this module.
+ */
+ def moduleClass: Symbol = NoSymbol
+
+ /** The non-private symbol whose type matches the type of this symbol
+ * in in given class.
+ *
+ * @param ofclazz The class containing the symbol's definition
+ * @param site The base type from which member types are computed
+ */
+ final def matchingSymbol(ofclazz: Symbol, site: Type): Symbol =
+ ofclazz.info.nonPrivateDecl(name).filter(sym =>
+ !sym.isTerm || (site.memberType(this) matches site.memberType(sym)))
+
+ /** The non-private member of `site' whose type and name match the type of this symbol
+ */
+ final def matchingSymbol(site: Type, admit: Long = 0L): Symbol =
+ site.nonPrivateMemberAdmitting(name, admit).filter(sym =>
+ !sym.isTerm || (site.memberType(this) matches site.memberType(sym)))
+
+ /** The symbol overridden by this symbol in given class `ofclazz'.
+ * @pre 'ofclazz' is a base class of this symbol's owner.
+ */
+ final def overriddenSymbol(ofclazz: Symbol): Symbol =
+ if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, owner.thisType)
+
+ /** The symbol overriding this symbol in given subclass `ofclazz'
+ * @pre: `ofclazz' is a subclass of this symbol's owner
+ */
+ final def overridingSymbol(ofclazz: Symbol): Symbol =
+ if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, ofclazz.thisType)
+
+ /** Returns all symbols overriden by this symbol
+ */
+ final def allOverriddenSymbols: List[Symbol] =
+ if (!owner.isClass) Nil
+ else owner.ancestors map overriddenSymbol filter (_ != NoSymbol)
+
+ /** Returns all symbols overridden by this symbol, plus all matching symbols
+ * defined in parents of the selftype
+ */
+ final def extendedOverriddenSymbols: List[Symbol] =
+ if (!owner.isClass) Nil
+ else owner.thisSym.ancestors map overriddenSymbol filter (_ != NoSymbol)
+
+ /** The symbol accessed by a super in the definition of this symbol when
+ * seen from class `base'. This symbol is always concrete.
+ * pre: `this.owner' is in the base class sequence of `base'.
+ */
+ final def superSymbol(base: Symbol): Symbol = {
+ var bcs = base.info.baseClasses.dropWhile(owner !=).tail
+ var sym: Symbol = NoSymbol
+ while (!bcs.isEmpty && sym == NoSymbol) {
+ if (!bcs.head.isImplClass)
+ sym = matchingSymbol(bcs.head, base.thisType).suchThat(!_.isDeferred)
+ bcs = bcs.tail
+ }
+ sym
+ }
+
+ /** The getter of this value or setter definition in class `base', or NoSymbol if
+ * none exists.
+ */
+ final def getter(base: Symbol): Symbol = {
+ val getterName = if (isSetter) nme.setterToGetter(name) else nme.getterName(name)
+ base.info.decl(getterName) filter (_.hasAccessorFlag)
+ }
+
+ /** The setter of this value or getter definition, or NoSymbol if none exists */
+ final def setter(base: Symbol): Symbol = setter(base, false)
+
+ final def setter(base: Symbol, hasExpandedName: Boolean): Symbol = {
+ var sname = nme.getterToSetter(nme.getterName(name))
+ if (hasExpandedName) sname = nme.expandedSetterName(sname, base)
+ base.info.decl(sname) filter (_.hasAccessorFlag)
+ }
+
+ /** The case module corresponding to this case class
+ * @pre case class is a member of some other class or package
+ */
+ final def caseModule: Symbol = {
+ var modname = name.toTermName
+ if (privateWithin.isClass && !privateWithin.isModuleClass && !hasFlag(EXPANDEDNAME))
+ modname = nme.expandedName(modname, privateWithin)
+ initialize.owner.info.decl(modname).suchThat(_.isModule)
+ }
+
+ /** If this symbol is a type parameter skolem (not an existential skolem!)
+ * its corresponding type parameter, otherwise this */
+ def deSkolemize: Symbol = this
+
+ /** If this symbol is an existential skolem the location (a Tree or null)
+ * where it was unpacked. Resulttype is AnyRef because trees are not visible here. */
+ def unpackLocation: AnyRef = null
+
+ /** Remove private modifier from symbol `sym's definition. If `sym' is a
+ * term symbol rename it by expanding its name to avoid name clashes
+ */
+ final def makeNotPrivate(base: Symbol) {
+ if (this hasFlag PRIVATE) {
+ setFlag(notPRIVATE)
+ if (isMethod && !isDeferred) setFlag(lateFINAL)
+ if (!isStaticModule && !isClassConstructor) {
+ expandName(base)
+ if (isModule) moduleClass.makeNotPrivate(base)
+ }
+ }
+ }
+
+ /** change name by appending $$<fully-qualified-name-of-class `base'>
+ * Do the same for any accessed symbols or setters/getters
+ */
+ def expandName(base: Symbol) {
+ if (this.isTerm && this != NoSymbol && !hasFlag(EXPANDEDNAME)) {
+ setFlag(EXPANDEDNAME)
+ if (hasAccessorFlag && !isDeferred) {
+ accessed.expandName(base)
+ } else if (hasGetter) {
+ getter(owner).expandName(base)
+ setter(owner).expandName(base)
+ }
+ name = nme.expandedName(name, base)
+ if (isType) name = name
+ }
+ }
+/* code for fixing nested objects
+ def expandModuleClassName() {
+ name = newTypeName(name.toString + "$")
+ }
+
+ def isExpandedModuleClass: Boolean = name(name.length - 1) == '$'
+*/
+ def sourceFile: AbstractFile =
+ if (isModule) moduleClass.sourceFile
+ else toplevelClass.sourceFile
+
+ def sourceFile_=(f: AbstractFile) {
+ abort("sourceFile_= inapplicable for " + this)
+ }
+
+ /** If this is a sealed class, its known direct subclasses.
+ * Otherwise, the empty set.
+ */
+ def children: Set[Symbol] = Set()
+
+ /** Recursively assemble all children of this symbol.
+ */
+ def sealedDescendants: Set[Symbol] = children.flatMap(_.sealedDescendants) + this
+
+ def orElse[T](alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt
+
+// ------ toString -------------------------------------------------------------------
+
+ /** A tag which (in the ideal case) uniquely identifies class symbols */
+ final def tag = fullName.##
+
+ /** The simple name of this Symbol */
+ final def simpleName: Name = name
+
+ /** The String used to order otherwise identical sealed symbols.
+ * This uses data which is stable across runs and variable classpaths
+ * (the initial Name) before falling back on id, which varies depending
+ * on exactly when a symbol is loaded.
+ */
+ final def sealedSortName = initName + "#" + id
+
+ /** String representation of symbol's definition key word */
+ final def keyString: String =
+ if (isJavaInterface) "interface"
+ else if (isTrait) "trait"
+ else if (isClass) "class"
+ else if (isType && !isParameter) "type"
+ else if (isVariable) "var"
+ else if (isPackage) "package"
+ else if (isModule) "object"
+ else if (isSourceMethod) "def"
+ else if (isTerm && (!isParameter || isParamAccessor)) "val"
+ else ""
+
+ /** Accurate string representation of symbols' kind, suitable for developers. */
+ final def accurateKindString: String =
+ if (isPackage) "package"
+ else if (isPackageClass) "package class"
+ else if (isPackageObject) "package object"
+ else if (isPackageObjectClass) "package object class"
+ else if (isRefinementClass) "refinement class"
+ else if (isModule) "module"
+ else if (isModuleClass) "module class"
+ else sanitizedKindString
+
+ /** String representation of symbol's kind, suitable for the masses. */
+ private def sanitizedKindString: String =
+ if (isPackage || isPackageClass) "package"
+ else if (isModule || isModuleClass) "object"
+ else if (isAnonymousClass) "anonymous class"
+ else if (isRefinementClass) ""
+ else if (isTrait) "trait"
+ else if (isClass) "class"
+ else if (isType) "type"
+ else if (isTerm && isLazy) "lazy value"
+ else if (isVariable) "variable"
+ else if (isClassConstructor) "constructor"
+ else if (isSourceMethod) "method"
+ else if (isTerm) "value"
+ else ""
+
+ final def kindString: String =
+ if (settings.debug.value) accurateKindString
+ else sanitizedKindString
+
+ /** If the name of the symbol's owner should be used when you care about
+ * seeing an interesting name: in such cases this symbol is e.g. a method
+ * parameter with a synthetic name, a constructor named "this", an object
+ * "package", etc. The kind string, if non-empty, will be phrased relative
+ * to the name of the owner.
+ */
+ def hasMeaninglessName = (
+ isSetterParameter // x$1
+ || isClassConstructor // this
+ || isPackageObject // package
+ || isPackageObjectClass // package$
+ || isRefinementClass // <refinement>
+ )
+
+ /** String representation of symbol's simple name.
+ * If !settings.debug translates expansions of operators back to operator symbol.
+ * E.g. $eq => =.
+ * If settings.uniqid, adds id.
+ */
+ def nameString = decodedName + idString
+
+ /** If settings.uniqid is set, the symbol's id, else "" */
+ final def idString = if (settings.uniqid.value) "#"+id else ""
+
+ /** String representation, including symbol's kind e.g., "class Foo", "method Bar".
+ * If hasMeaninglessName is true, uses the owner's name to disambiguate identity.
+ */
+ override def toString = compose(
+ kindString,
+ if (hasMeaninglessName) owner.nameString else nameString
+ )
+
+ /** String representation of location.
+ */
+ def ownsString = {
+ val owns = owner.skipPackageObject
+ if (owns.isClass && !owns.printWithoutPrefix && !isScalaPackageClass) "" + owns
+ else ""
+ }
+
+ /** String representation of location, plus a preposition. Doesn't do much,
+ * for backward compatibility reasons.
+ */
+ def locationString = ownsString match {
+ case "" => ""
+ case s => " in " + s
+ }
+ def fullLocationString = toString + locationString
+
+ /** String representation of symbol's definition following its name */
+ final def infoString(tp: Type): String = {
+ def typeParamsString: String = tp match {
+ case PolyType(tparams, _) if tparams.nonEmpty =>
+ (tparams map (_.defString)).mkString("[", ",", "]")
+ case _ =>
+ ""
+ }
+ if (isClass)
+ typeParamsString + " extends " + tp.resultType
+ else if (isAliasType)
+ typeParamsString + " = " + tp.resultType
+ else if (isAbstractType)
+ typeParamsString + {
+ tp.resultType match {
+ case TypeBounds(lo, hi) =>
+ (if (lo.typeSymbol == NothingClass) "" else " >: " + lo) +
+ (if (hi.typeSymbol == AnyClass) "" else " <: " + hi)
+ case rtp =>
+ "<: " + rtp
+ }
+ }
+ else if (isModule)
+ moduleClass.infoString(tp)
+ else
+ tp match {
+ case PolyType(tparams, res) =>
+ typeParamsString + infoString(res)
+ case NullaryMethodType(res) =>
+ infoString(res)
+ case MethodType(params, res) =>
+ params.map(_.defString).mkString("(", ",", ")") + infoString(res)
+ case _ =>
+ ": " + tp
+ }
+ }
+
+ def infosString = infos.toString()
+
+ def hasFlagsToString(mask: Long): String = flagsToString(
+ flags & mask,
+ if (hasAccessBoundary) privateWithin.toString else ""
+ )
+
+ /** String representation of symbol's variance */
+ def varianceString: String =
+ if (variance == 1) "+"
+ else if (variance == -1) "-"
+ else ""
+
+ def defaultFlagMask =
+ if (settings.debug.value) -1L
+ else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE
+ else ExplicitFlags
+
+ def defaultFlagString = hasFlagsToString(defaultFlagMask)
+
+ /** String representation of symbol's definition */
+ def defString = compose(
+ defaultFlagString,
+ keyString,
+ varianceString + nameString + (
+ if (hasRawInfo) infoString(rawInfo) else "<_>"
+ )
+ )
+
+ /** Concatenate strings separated by spaces */
+ private def compose(ss: String*) = ss filter (_ != "") mkString " "
+
+ def isSingletonExistential =
+ nme.isSingletonName(name) && (info.bounds.hi.typeSymbol isSubClass SingletonClass)
+
+ /** String representation of existentially bound variable */
+ def existentialToString =
+ if (isSingletonExistential && !settings.debug.value)
+ "val " + nme.dropSingletonName(name) + ": " + dropSingletonType(info.bounds.hi)
+ else defString
+ }
+
+ /** A class for term symbols */
+ class TermSymbol(initOwner: Symbol, initPos: Position, initName: TermName)
+ extends Symbol(initOwner, initPos, initName) {
+ final override def isTerm = true
+
+ override def name: TermName = super.name
+ privateWithin = NoSymbol
+
+ var referenced: Symbol = NoSymbol
+
+ def cloneSymbolImpl(owner: Symbol): Symbol =
+ new TermSymbol(owner, pos, name).copyAttrsFrom(this)
+
+ def copyAttrsFrom(original: TermSymbol): this.type = {
+ referenced = original.referenced
+ this
+ }
+
+ private val validAliasFlags = SUPERACCESSOR | PARAMACCESSOR | MIXEDIN | SPECIALIZED
+
+ override def alias: Symbol =
+ if (hasFlag(validAliasFlags)) initialize.referenced
+ else NoSymbol
+
+ def setAlias(alias: Symbol): TermSymbol = {
+ assert(alias != NoSymbol, this)
+ assert(!alias.isOverloaded, alias)
+ assert(hasFlag(validAliasFlags), this)
+
+ referenced = alias
+ this
+ }
+
+ override def outerSource: Symbol =
+ if (name endsWith nme.OUTER) initialize.referenced
+ else NoSymbol
+
+ override def moduleClass: Symbol =
+ if (hasFlag(MODULE)) referenced else NoSymbol
+
+ def setModuleClass(clazz: Symbol): TermSymbol = {
+ assert(hasFlag(MODULE))
+ referenced = clazz
+ this
+ }
+
+ def setLazyAccessor(sym: Symbol): TermSymbol = {
+ assert(isLazy && (referenced == NoSymbol || referenced == sym), this)
+ referenced = sym
+ this
+ }
+
+ override def lazyAccessor: Symbol = {
+ assert(isLazy, this)
+ referenced
+ }
+
+ protected def doCookJavaRawInfo() {
+ def cook(sym: Symbol) {
+ require(sym hasFlag JAVA)
+ // @M: I think this is more desirable, but Martin prefers to leave raw-types as-is as much as possible
+ // object rawToExistentialInJava extends TypeMap {
+ // def apply(tp: Type): Type = tp match {
+ // // any symbol that occurs in a java sig, not just java symbols
+ // // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14
+ // case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty =>
+ // val eparams = typeParamsToExistentials(sym, sym.typeParams)
+ // existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe)))
+ // case _ =>
+ // mapOver(tp)
+ // }
+ // }
+ val tpe1 = rawToExistential(sym.tpe)
+ // println("cooking: "+ sym +": "+ sym.tpe +" to "+ tpe1)
+ if (tpe1 ne sym.tpe) {
+ sym.setInfo(tpe1)
+ }
+ }
+
+ if (isJavaDefined)
+ cook(this)
+ else if (hasFlag(OVERLOADED))
+ for (sym2 <- alternatives)
+ if (sym2 hasFlag JAVA)
+ cook(sym2)
+ }
+ }
+
+ /** A class for module symbols */
+ class ModuleSymbol(initOwner: Symbol, initPos: Position, initName: TermName)
+ extends TermSymbol(initOwner, initPos, initName) {
+ private var flatname: TermName = null
+ // This method could use a better name from someone clearer on what the condition expresses.
+ private def isFlatAdjusted = !isMethod && needsFlatClasses
+
+ override def owner: Symbol =
+ if (isFlatAdjusted) rawowner.owner
+ else rawowner
+
+ override def name: TermName =
+ if (isFlatAdjusted) {
+ if (flatname == null)
+ flatname = flattenName().toTermName
+
+ flatname
+ } else rawname
+
+ override def cloneSymbolImpl(owner: Symbol): Symbol =
+ new ModuleSymbol(owner, pos, name).copyAttrsFrom(this)
+ }
+
+ /** A class for method symbols */
+ class MethodSymbol(initOwner: Symbol, initPos: Position, initName: TermName)
+ extends TermSymbol(initOwner, initPos, initName) {
+ private var mtpePeriod = NoPeriod
+ private var mtpePre: Type = _
+ private var mtpeResult: Type = _
+ private var mtpeInfo: Type = _
+
+ override def cloneSymbolImpl(owner: Symbol): Symbol =
+ new MethodSymbol(owner, pos, name).copyAttrsFrom(this)
+
+ def typeAsMemberOf(pre: Type): Type = {
+ if (mtpePeriod == currentPeriod) {
+ if ((mtpePre eq pre) && (mtpeInfo eq info)) return mtpeResult
+ } else if (isValid(mtpePeriod)) {
+ mtpePeriod = currentPeriod
+ if ((mtpePre eq pre) && (mtpeInfo eq info)) return mtpeResult
+ }
+ val res = pre.computeMemberType(this)
+ mtpePeriod = currentPeriod
+ mtpePre = pre
+ mtpeInfo = info
+ mtpeResult = res
+ res
+ }
+ }
+
+ /** A class of type symbols. Alias and abstract types are direct instances
+ * of this class. Classes are instances of a subclass.
+ */
+ class TypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
+ extends Symbol(initOwner, initPos, initName) {
+ privateWithin = NoSymbol
+ private var tyconCache: Type = null
+ private var tyconRunId = NoRunId
+ private var tpeCache: Type = _
+ private var tpePeriod = NoPeriod
+
+ override def name: TypeName = super.name.asInstanceOf[TypeName]
+ final override def isType = true
+ override def isNonClassType = true
+ override def isAbstractType = isDeferred
+ override def isAliasType = !isDeferred
+
+ private def newTypeRef(targs: List[Type]) = {
+ val pre = if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType
+ typeRef(pre, this, targs)
+ }
+
+ /** Let's say you have a type definition
+ *
+ * type T <: Number
+ *
+ * and tsym is the symbol corresponding to T. Then
+ *
+ * tsym.info = TypeBounds(Nothing, Number)
+ * tsym.tpe = TypeRef(NoPrefix, T, List())
+ */
+ override def tpe: Type = {
+ if (tpeCache eq NoType) throw CyclicReference(this, typeConstructor)
+ if (tpePeriod != currentPeriod) {
+ if (isValid(tpePeriod)) {
+ tpePeriod = currentPeriod
+ } else {
+ if (isInitialized) tpePeriod = currentPeriod
+ tpeCache = NoType
+ val targs =
+ if (phase.erasedTypes && this != ArrayClass) List()
+ else unsafeTypeParams map (_.typeConstructor) //@M! use typeConstructor to generate dummy type arguments,
+ // sym.tpe should not be called on a symbol that's supposed to be a higher-kinded type
+ // memberType should be used instead, that's why it uses tpeHK and not tpe
+ tpeCache = newTypeRef(targs)
+ }
+ }
+ assert(tpeCache ne null/*, "" + this + " " + phase*/)//debug
+ tpeCache
+ }
+
+ // needed for experimental code for early types as type parameters
+ // def refreshType() { tpePeriod = NoPeriod }
+
+ override def typeConstructor: Type = {
+ if ((tyconCache eq null) || tyconRunId != currentRunId) {
+ tyconCache = newTypeRef(Nil)
+ tyconRunId = currentRunId
+ }
+ assert(tyconCache ne null)
+ tyconCache
+ }
+
+ override def info_=(tp: Type) {
+ tpePeriod = NoPeriod
+ tyconCache = null
+ super.info_=(tp)
+ }
+
+ override def reset(completer: Type) {
+ super.reset(completer)
+ tpePeriod = NoPeriod
+ tyconRunId = NoRunId
+ }
+
+ /*** example:
+ * public class Test3<T> {}
+ * public class Test1<T extends Test3> {}
+ * info for T in Test1 should be >: Nothing <: Test3[_]
+ */
+ protected def doCookJavaRawInfo() {
+ // don't require isJavaDefined, since T in the above example does not have that flag
+ val tpe1 = rawToExistential(info)
+ // println("cooking type: "+ this +": "+ info +" to "+ tpe1)
+ if (tpe1 ne info) {
+ setInfo(tpe1)
+ }
+ }
+
+ def cloneSymbolImpl(owner: Symbol): Symbol =
+ new TypeSymbol(owner, pos, name) //.toTypeName)
+
+ incCounter(typeSymbolCount)
+ }
+
+ /** A class for type parameters viewed from inside their scopes
+ *
+ * @param origin Can be either a tree, or a symbol, or null.
+ * If skolem got created from newTypeSkolem (called in Namers), origin denotes
+ * the type parameter from which the skolem was created. If it got created from
+ * skolemizeExistential, origin is either null or a Tree. If it is a Tree, it indicates
+ * where the skolem was introduced (this is important for knowing when to pack it
+ * again into ab Existential). origin is `null' only in skolemizeExistentials called
+ * from <:< or isAsSpecific, because here its value does not matter.
+ * I elieve the following invariant holds:
+ *
+ * origin.isInstanceOf[Symbol] == !hasFlag(EXISTENTIAL)
+ */
+ class TypeSkolem(initOwner: Symbol, initPos: Position, initName: TypeName, origin: AnyRef)
+ extends TypeSymbol(initOwner, initPos, initName) {
+
+ /** The skolemization level in place when the skolem was constructed */
+ val level = skolemizationLevel
+
+ final override def isSkolem = true
+
+ /** If typeskolem comes from a type parameter, that parameter, otherwise skolem itself */
+ override def deSkolemize = origin match {
+ case s: Symbol => s
+ case _ => this
+ }
+
+ /** If type skolem comes from an existential, the tree where it was created */
+ override def unpackLocation = origin
+
+ override def typeParams = info.typeParams //@M! (not deSkolemize.typeParams!!), also can't leave superclass definition: use info, not rawInfo
+
+ override def cloneSymbolImpl(owner: Symbol): Symbol =
+ new TypeSkolem(owner, pos, name, origin)
+
+ override def nameString: String =
+ if (settings.debug.value) (super.nameString + "&" + level)
+ else super.nameString
+ }
+
+
+ /** A class for class symbols */
+ class ClassSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
+ extends TypeSymbol(initOwner, initPos, initName) {
+
+ private var source: AbstractFile = null
+ private var thissym: Symbol = this
+
+ final override def isClass = true
+ final override def isNonClassType = false
+ final override def isAbstractType = false
+ final override def isAliasType = false
+
+ override def sourceFile =
+ if (owner.isPackageClass) source
+ else super.sourceFile
+ override def sourceFile_=(f: AbstractFile) { source = f }
+
+ override def reset(completer: Type) {
+ super.reset(completer)
+ thissym = this
+ }
+
+ private var flatname: TypeName = null
+
+ override def owner: Symbol =
+ if (needsFlatClasses) rawowner.owner
+ else rawowner
+
+ override def name: TypeName =
+ if (needsFlatClasses) {
+ if (flatname == null)
+ flatname = flattenName().toTypeName
+ flatname
+ }
+ else rawname.asInstanceOf[TypeName]
+
+ private var thisTypeCache: Type = _
+ private var thisTypePeriod = NoPeriod
+
+ private var typeOfThisCache: Type = _
+ private var typeOfThisPeriod = NoPeriod
+
+ /** the type this.type in this class */
+ override def thisType: Type = {
+ val period = thisTypePeriod
+ if (period != currentPeriod) {
+ thisTypePeriod = currentPeriod
+ if (!isValid(period)) thisTypeCache = ThisType(this)
+ }
+ thisTypeCache
+ }
+
+ /** A symbol carrying the self type of the class as its type */
+ override def thisSym: Symbol = thissym
+
+ /** the self type of an object foo is foo.type, not class<foo>.this.type
+ */
+ override def typeOfThis: Type = {
+ if (getFlag(MODULE | IMPLCLASS) == MODULE.toLong && owner != NoSymbol) {
+ val period = typeOfThisPeriod
+ if (period != currentPeriod) {
+ typeOfThisPeriod = currentPeriod
+ if (!isValid(period))
+ typeOfThisCache = singleType(owner.thisType, sourceModule)
+ }
+ typeOfThisCache
+ }
+ else thissym.tpe
+ }
+
+ /** Sets the self type of the class */
+ override def typeOfThis_=(tp: Type) {
+ thissym = newThisSym(pos).setInfo(tp)
+ }
+
+ override def cloneSymbolImpl(owner: Symbol): Symbol = {
+ val clone = new ClassSymbol(owner, pos, name)
+ if (thisSym != this) {
+ clone.typeOfThis = typeOfThis
+ clone.thisSym.name = thisSym.name
+ }
+ clone
+ }
+
+ override def sourceModule =
+ if (isModuleClass) companionModule else NoSymbol
+
+ private var childSet: Set[Symbol] = Set()
+ override def children = childSet
+ override def addChild(sym: Symbol) { childSet = childSet + sym }
+
+ incCounter(classSymbolCount)
+ }
+
+ /** A class for module class symbols
+ * Note: Not all module classes are of this type; when unpickled, we get
+ * plain class symbols!
+ */
+ class ModuleClassSymbol(owner: Symbol, pos: Position, name: TypeName)
+ extends ClassSymbol(owner, pos, name) {
+ private var module: Symbol = null
+ def this(module: TermSymbol) = {
+ this(module.owner, module.pos, module.name.toTypeName)
+ setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL)
+ sourceModule = module
+ }
+ override def sourceModule = module
+ private var implicitMembersCacheValue: List[Symbol] = List()
+ private var implicitMembersCacheKey: Type = NoType
+ def implicitMembers: List[Symbol] = {
+ val tp = info
+ if (implicitMembersCacheKey ne tp) {
+ implicitMembersCacheKey = tp
+ implicitMembersCacheValue = tp.implicitMembers
+ }
+ implicitMembersCacheValue
+ }
+ override def sourceModule_=(module: Symbol) { this.module = module }
+ }
+
+ /** An object representing a missing symbol */
+ object NoSymbol extends Symbol(null, NoPosition, nme.NO_NAME) {
+ setInfo(NoType)
+ privateWithin = this
+ override def info_=(info: Type) {
+ infos = TypeHistory(1, NoType, null)
+ unlock()
+ validTo = currentPeriod
+ }
+ override def defString: String = toString
+ override def locationString: String = ""
+ override def enclClass: Symbol = this
+ override def toplevelClass: Symbol = this
+ override def enclMethod: Symbol = this
+ override def owner: Symbol = abort("no-symbol does not have owner")
+ override def sourceFile: AbstractFile = null
+ override def ownerChain: List[Symbol] = List()
+ override def ownersIterator: Iterator[Symbol] = Iterator.empty
+ override def alternatives: List[Symbol] = List()
+ override def reset(completer: Type) {}
+ override def info: Type = NoType
+ override def rawInfo: Type = NoType
+ protected def doCookJavaRawInfo() {}
+ override def accessBoundary(base: Symbol): Symbol = RootClass
+ def cloneSymbolImpl(owner: Symbol): Symbol = abort()
+ override def originalEnclosingMethod = this
+ }
+
+ def cloneSymbols[T <: Symbol](syms: List[T]): List[T] = {
+ val syms1 = syms map (_.cloneSymbol.asInstanceOf[T])
+ for (sym1 <- syms1) sym1.setInfo(sym1.info.substSym(syms, syms1))
+ syms1
+ }
+
+ def cloneSymbols[T <: Symbol](syms: List[T], owner: Symbol): List[T] = {
+ val syms1 = syms map (_.cloneSymbol(owner).asInstanceOf[T])
+ for (sym1 <- syms1) sym1.setInfo(sym1.info.substSym(syms, syms1))
+ syms1
+ }
+
+ /** An exception for cyclic references of symbol definitions */
+ case class CyclicReference(sym: Symbol, info: Type)
+ extends TypeError("illegal cyclic reference involving " + sym) {
+ // printStackTrace() // debug
+ }
+
+ case class InvalidCompanions(sym1: Symbol, sym2: Symbol)
+ extends Throwable("Companions '" + sym1 + "' and '" + sym2 + "' must be defined in same file") {
+ override def toString = getMessage
+ }
+
+ /** A class for type histories */
+ private sealed case class TypeHistory(var validFrom: Period, info: Type, prev: TypeHistory) {
+ assert((prev eq null) || phaseId(validFrom) > phaseId(prev.validFrom), this)
+ assert(validFrom != NoPeriod)
+ override def toString() =
+ "TypeHistory(" + phaseOf(validFrom)+":"+runId(validFrom) + "," + info + "," + prev + ")"
+ }
+}
diff --git a/src/compiler/scala/reflect/common/TreeGen.scala b/src/compiler/scala/reflect/common/TreeGen.scala
new file mode 100644
index 0000000000..5d43e0f26e
--- /dev/null
+++ b/src/compiler/scala/reflect/common/TreeGen.scala
@@ -0,0 +1,234 @@
+package scala.reflect
+package common
+
+abstract class TreeGen {
+ val global: SymbolTable
+
+ import global._
+ import definitions._
+
+ def rootId(name: Name) = Select(Ident(nme.ROOTPKG), name)
+ def rootScalaDot(name: Name) = Select(rootId(nme.scala_) setSymbol ScalaPackage, name)
+ def scalaDot(name: Name) = Select(Ident(nme.scala_) setSymbol ScalaPackage, name)
+ def scalaAnyRefConstr = scalaDot(tpnme.AnyRef)
+ def scalaUnitConstr = scalaDot(tpnme.Unit)
+ def scalaScalaObjectConstr = scalaDot(tpnme.ScalaObject)
+ def productConstr = scalaDot(tpnme.Product)
+ def serializableConstr = scalaDot(tpnme.Serializable)
+
+ def scalaFunctionConstr(argtpes: List[Tree], restpe: Tree, abstractFun: Boolean = false): Tree = {
+ val cls = if (abstractFun)
+ mkAttributedRef(AbstractFunctionClass(argtpes.length))
+ else
+ mkAttributedRef(FunctionClass(argtpes.length))
+ AppliedTypeTree(cls, argtpes :+ restpe)
+ }
+
+ /** Builds a reference to value whose type is given stable prefix.
+ * The type must be suitable for this. For example, it
+ * must not be a TypeRef pointing to an abstract type variable.
+ */
+ def mkAttributedQualifier(tpe: Type): Tree =
+ mkAttributedQualifier(tpe, NoSymbol)
+
+ /** Builds a reference to value whose type is given stable prefix.
+ * If the type is unsuitable, e.g. it is a TypeRef for an
+ * abstract type variable, then an Ident will be made using
+ * termSym as the Ident's symbol. In that case, termSym must
+ * not be NoSymbol.
+ */
+ def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = tpe match {
+ case NoPrefix =>
+ EmptyTree
+ case ThisType(clazz) =>
+ if (clazz.isEffectiveRoot) EmptyTree
+ else mkAttributedThis(clazz)
+ case SingleType(pre, sym) =>
+ applyIfNoArgs(mkAttributedStableRef(pre, sym))
+ case TypeRef(pre, sym, args) =>
+ if (sym.isRoot) {
+ mkAttributedThis(sym)
+ } else if (sym.isModuleClass) {
+ applyIfNoArgs(mkAttributedRef(pre, sym.sourceModule))
+ } else if (sym.isModule || sym.isClass) {
+ assert(phase.erasedTypes, tpe)
+ mkAttributedThis(sym)
+ } else if (sym.isType) {
+ assert(termSym != NoSymbol, tpe)
+ mkAttributedIdent(termSym) setType tpe
+ } else {
+ mkAttributedRef(pre, sym)
+ }
+
+ case ConstantType(value) =>
+ Literal(value) setType tpe
+
+ case AnnotatedType(_, atp, _) =>
+ mkAttributedQualifier(atp)
+
+ case RefinedType(parents, _) =>
+ // I am unclear whether this is reachable, but
+ // the following implementation looks logical -Lex
+ val firstStable = parents.find(_.isStable)
+ assert(!firstStable.isEmpty, tpe)
+ mkAttributedQualifier(firstStable.get)
+
+ case _ =>
+ abort("bad qualifier: " + tpe)
+ }
+ /** If this is a reference to a method with an empty
+ * parameter list, wrap it in an apply.
+ */
+ private def applyIfNoArgs(qual: Tree) = qual.tpe match {
+ case MethodType(Nil, restpe) => Apply(qual, Nil) setType restpe
+ case _ => qual
+ }
+
+ /** Builds a reference to given symbol with given stable prefix. */
+ def mkAttributedRef(pre: Type, sym: Symbol): Tree = {
+ val qual = mkAttributedQualifier(pre)
+ qual match {
+ case EmptyTree => mkAttributedIdent(sym)
+ case This(clazz) if qual.symbol.isEffectiveRoot => mkAttributedIdent(sym)
+ case _ => mkAttributedSelect(qual, sym)
+ }
+ }
+
+ /** Builds a reference to given symbol. */
+ def mkAttributedRef(sym: Symbol): Tree =
+ if (sym.owner.isClass) mkAttributedRef(sym.owner.thisType, sym)
+ else mkAttributedIdent(sym)
+
+ /** Builds an untyped reference to given symbol. */
+ def mkUnattributedRef(sym: Symbol): Tree =
+ if (sym.owner.isClass) Select(This(sym.owner), sym)
+ else Ident(sym)
+
+ /** Replaces tree type with a stable type if possible */
+ def stabilize(tree: Tree): Tree = {
+ for(tp <- stableTypeFor(tree)) tree.tpe = tp
+ tree
+ }
+
+ /** Computes stable type for a tree if possible */
+ def stableTypeFor(tree: Tree): Option[Type] = tree match {
+ case Ident(_) if tree.symbol.isStable =>
+ Some(singleType(tree.symbol.owner.thisType, tree.symbol))
+ case Select(qual, _) if ((tree.symbol ne null) && (qual.tpe ne null)) && // turned assert into guard for #4064
+ tree.symbol.isStable && qual.tpe.isStable =>
+ Some(singleType(qual.tpe, tree.symbol))
+ case _ =>
+ None
+ }
+
+ /** Cast `tree' to type `pt' */
+ def mkCast(tree: Tree, pt: Type): Tree = {
+ if (settings.debug.value) log("casting " + tree + ":" + tree.tpe + " to " + pt)
+ assert(!tree.tpe.isInstanceOf[MethodType], tree)
+ assert(!pt.typeSymbol.isPackageClass)
+ assert(!pt.typeSymbol.isPackageObjectClass)
+ assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize)) //@MAT only called during erasure, which already takes care of that
+ atPos(tree.pos)(mkAsInstanceOf(tree, pt, false))
+ }
+
+ /** Builds a reference with stable type to given symbol */
+ def mkAttributedStableRef(pre: Type, sym: Symbol): Tree =
+ stabilize(mkAttributedRef(pre, sym))
+
+ def mkAttributedStableRef(sym: Symbol): Tree =
+ stabilize(mkAttributedRef(sym))
+
+ def mkAttributedThis(sym: Symbol): Tree =
+ This(sym.name.toTypeName) setSymbol sym setType sym.thisType
+
+ def mkAttributedIdent(sym: Symbol): Tree =
+ Ident(sym.name) setSymbol sym setType sym.tpe
+
+ def mkAttributedSelect(qual: Tree, sym: Symbol): Tree = {
+ // Tests involving the repl fail without the .isEmptyPackage condition.
+ if (qual.symbol != null && (qual.symbol.isEffectiveRoot || qual.symbol.isEmptyPackage))
+ mkAttributedIdent(sym)
+ else {
+ val pkgQualifier =
+ if (sym != null && sym.owner.isPackageObjectClass && sym.owner.owner == qual.tpe.typeSymbol) {
+ val obj = sym.owner.sourceModule
+ Select(qual, nme.PACKAGEkw) setSymbol obj setType singleType(qual.tpe, obj)
+ }
+ else qual
+
+ val tree = Select(pkgQualifier, sym)
+ if (pkgQualifier.tpe == null) tree
+ else tree setType (qual.tpe memberType sym)
+ }
+ }
+
+ private def mkTypeApply(value: Tree, tpe: Type, what: Symbol) =
+ Apply(
+ TypeApply(
+ mkAttributedSelect(value, what),
+ List(TypeTree(tpe.normalize))
+ ),
+ Nil
+ )
+ /** Builds an instance test with given value and type. */
+ def mkIsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree =
+ mkTypeApply(value, tpe, (if (any) Any_isInstanceOf else Object_isInstanceOf))
+
+ /** Builds a cast with given value and type. */
+ def mkAsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree =
+ mkTypeApply(value, tpe, (if (any) Any_asInstanceOf else Object_asInstanceOf))
+
+ /** Cast `tree' to 'pt', unless tpe is a subtype of pt, or pt is Unit. */
+ def maybeMkAsInstanceOf(tree: Tree, pt: Type, tpe: Type, beforeRefChecks: Boolean = false): Tree =
+ if ((pt == UnitClass.tpe) || (tpe <:< pt)) {
+ log("no need to cast from " + tpe + " to " + pt)
+ tree
+ } else
+ atPos(tree.pos) {
+ if (beforeRefChecks)
+ TypeApply(mkAttributedSelect(tree, Any_asInstanceOf), List(TypeTree(pt)))
+ else
+ mkAsInstanceOf(tree, pt)
+ }
+
+ def mkClassOf(tp: Type): Tree =
+ Literal(Constant(tp)) setType ConstantType(Constant(tp))// ClassType(tp)
+
+ /** Builds a list with given head and tail. */
+ def mkNewCons(head: Tree, tail: Tree): Tree =
+ New(Apply(mkAttributedRef(ConsClass), List(head, tail)))
+
+ /** Builds a list with given head and tail. */
+ def mkNil: Tree = mkAttributedRef(NilModule)
+
+ /** Builds a tree representing an undefined local, as in
+ * var x: T = _
+ * which is appropriate to the given Type.
+ */
+ def mkZero(tp: Type): Tree = {
+ val sym = tp.typeSymbol
+ val tree =
+ if (sym == UnitClass) Literal(())
+ else if (sym == BooleanClass) Literal(false)
+ else if (isValueClass(sym)) Literal(0)
+ else if (NullClass.tpe <:< tp) Literal(null: Any)
+ else abort("Cannot determine zero for " + tp)
+
+ tree setType tp
+ }
+
+ /** Builds a tuple */
+ def mkTuple(elems: List[Tree]): Tree =
+ if (elems.isEmpty) Literal(())
+ else Apply(
+ Select(mkAttributedRef(TupleClass(elems.length).caseModule), nme.apply),
+ elems)
+
+ // tree1 AND tree2
+ def mkAnd(tree1: Tree, tree2: Tree): Tree =
+ Apply(Select(tree1, Boolean_and), List(tree2))
+
+ // tree1 OR tree2
+ def mkOr(tree1: Tree, tree2: Tree): Tree =
+ Apply(Select(tree1, Boolean_or), List(tree2))
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/reflect/common/TreeInfo.scala
index 5184ebad19..95189d1813 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/reflect/common/TreeInfo.scala
@@ -3,11 +3,10 @@
* @author Martin Odersky
*/
-package scala.tools.nsc
-package ast
+package scala.reflect
+package common
-import symtab.Flags._
-import symtab.SymbolTable
+import Flags._
import util.HashSet
/** This class ...
@@ -356,7 +355,6 @@ abstract class TreeInfo {
|| containsLeadingPredefImport(List(body)))
}
-
def isAbsTypeDef(tree: Tree) = tree match {
case TypeDef(_, _, _, TypeBoundsTree(_, _)) => true
case TypeDef(_, _, _, rhs) => rhs.tpe.isInstanceOf[TypeBounds]
diff --git a/src/compiler/scala/reflect/common/TreePrinters.scala b/src/compiler/scala/reflect/common/TreePrinters.scala
new file mode 100644
index 0000000000..711232d774
--- /dev/null
+++ b/src/compiler/scala/reflect/common/TreePrinters.scala
@@ -0,0 +1,461 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+import java.io.{ OutputStream, PrintWriter, StringWriter, Writer }
+import Flags._
+
+trait TreePrinters { self: SymbolTable =>
+
+ //nsc import treeInfo.{ IsTrue, IsFalse }
+
+ final val showOuterTests = false
+
+ /** Adds backticks if the name is a scala keyword. */
+ def quotedName(name: Name, decode: Boolean): String = {
+ val s = if (decode) name.decode else name.toString
+ val term = name.toTermName
+ if (nme.keywords(term) && term != nme.USCOREkw) "`%s`" format s
+ else s
+ }
+ def quotedName(name: Name): String = quotedName(name, false)
+
+ /** Turns a path into a String, introducing backquotes
+ * as necessary.
+ */
+ def backquotedPath(t: Tree): String = t match {
+ case Select(qual, name) => "%s.%s".format(backquotedPath(qual), quotedName(name))
+ case Ident(name) => quotedName(name)
+ case _ => t.toString
+ }
+
+ class TreePrinter(out: PrintWriter) {
+ protected var indentMargin = 0
+ protected val indentStep = 2
+ protected var indentString = " " // 40
+
+ def flush() = out.flush()
+
+ def indent() = indentMargin += indentStep
+ def undent() = indentMargin -= indentStep
+
+ protected def doPrintPositions = settings.Xprintpos.value
+ def printPosition(tree: Tree) = if (doPrintPositions) print(showPos(tree.pos))
+
+ def println() {
+ out.println()
+ while (indentMargin > indentString.length())
+ indentString += indentString
+ if (indentMargin > 0)
+ out.write(indentString, 0, indentMargin)
+ }
+
+ def printSeq[a](ls: List[a])(printelem: a => Unit)(printsep: => Unit) {
+ ls match {
+ case List() =>
+ case List(x) => printelem(x)
+ case x :: rest => printelem(x); printsep; printSeq(rest)(printelem)(printsep)
+ }
+ }
+
+ def printColumn(ts: List[Tree], start: String, sep: String, end: String) {
+ print(start); indent; println()
+ printSeq(ts){print}{print(sep); println()}; undent; println(); print(end)
+ }
+
+ def printRow(ts: List[Tree], start: String, sep: String, end: String) {
+ print(start); printSeq(ts){print}{print(sep)}; print(end)
+ }
+
+ def printRow(ts: List[Tree], sep: String) { printRow(ts, "", sep, "") }
+
+ def printTypeParams(ts: List[TypeDef]) {
+ if (!ts.isEmpty) {
+ print("["); printSeq(ts){ t =>
+ printAnnotations(t)
+ printParam(t)
+ }{print(", ")}; print("]")
+ }
+ }
+
+ def printValueParams(ts: List[ValDef]) {
+ print("(")
+ if (!ts.isEmpty) printFlags(ts.head.mods.flags & IMPLICIT, "")
+ printSeq(ts){printParam}{print(", ")}
+ print(")")
+ }
+
+ def printParam(tree: Tree) {
+ tree match {
+ case ValDef(mods, name, tp, rhs) =>
+ printPosition(tree)
+ printAnnotations(tree)
+ print(symName(tree, name)); printOpt(": ", tp); printOpt(" = ", rhs)
+ case TypeDef(mods, name, tparams, rhs) =>
+ printPosition(tree)
+ print(symName(tree, name))
+ printTypeParams(tparams); print(rhs)
+ }
+ }
+
+ def printBlock(tree: Tree) {
+ tree match {
+ case Block(_, _) =>
+ print(tree)
+ case _ =>
+ printColumn(List(tree), "{", ";", "}")
+ }
+ }
+
+ private def symFn[T](tree: Tree, f: Symbol => T, orElse: => T): T = tree.symbol match {
+ case null | NoSymbol => orElse
+ case sym => f(sym)
+ }
+ private def ifSym(tree: Tree, p: Symbol => Boolean) = symFn(tree, p, false)
+
+ private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = {
+ def nameFn(sym: Symbol) = {
+ val prefix = if (sym.isMixinConstructor) "/*%s*/".format(quotedName(sym.owner.name, decoded)) else ""
+ prefix + tree.symbol.nameString
+ }
+ symFn(tree, nameFn, quotedName(name, decoded))
+ }
+
+ def decodedSymName(tree: Tree, name: Name) = symNameInternal(tree, name, true)
+ def symName(tree: Tree, name: Name) = symNameInternal(tree, name, false)
+
+ def printOpt(prefix: String, tree: Tree) {
+ if (!tree.isEmpty) { print(prefix); print(tree) }
+ }
+
+ def printModifiers(tree: Tree, mods: Modifiers): Unit = printFlags(
+ if (tree.symbol == NoSymbol) mods.flags else tree.symbol.flags, "" + (
+ if (tree.symbol == NoSymbol) mods.privateWithin
+ else if (tree.symbol.hasAccessBoundary) tree.symbol.privateWithin.name
+ else ""
+ )
+ )
+
+ def printFlags(flags: Long, privateWithin: String) {
+ var mask: Long = if (settings.debug.value) -1L else PrintableFlags
+ val s = flagsToString(flags & mask, privateWithin)
+ if (s != "") print(s + " ")
+ }
+
+ def printAnnotations(tree: Tree) {
+ val annots =
+ if (tree.symbol.hasAssignedAnnotations) tree.symbol.annotations
+ else tree.asInstanceOf[MemberDef].mods.annotations
+
+ annots foreach (annot => print("@"+annot+" "))
+ }
+
+ def print(str: String) { out.print(str) }
+ def print(name: Name) { print(quotedName(name)) }
+
+ private var currentOwner: Symbol = NoSymbol
+ private var selectorType: Type = NoType
+
+ def printRaw(tree: Tree) {
+ tree match {
+ case EmptyTree =>
+ print("<empty>")
+
+ case ClassDef(mods, name, tparams, impl) =>
+ printAnnotations(tree)
+ printModifiers(tree, mods)
+ val word =
+ if (mods.hasTraitFlag) "trait"
+ else if (ifSym(tree, _.isModuleClass)) "object"
+ else "class"
+
+ print(word + " " + symName(tree, name))
+ printTypeParams(tparams)
+ print(if (mods.isDeferred) " <: " else " extends "); print(impl)
+
+ case PackageDef(packaged, stats) =>
+ printAnnotations(tree)
+ print("package "); print(packaged); printColumn(stats, " {", ";", "}")
+
+ case ModuleDef(mods, name, impl) =>
+ printAnnotations(tree)
+ printModifiers(tree, mods); print("object " + symName(tree, name))
+ print(" extends "); print(impl)
+
+ case ValDef(mods, name, tp, rhs) =>
+ printAnnotations(tree)
+ printModifiers(tree, mods)
+ print(if (mods.isMutable) "var " else "val ")
+ print(symName(tree, name))
+ printOpt(": ", tp)
+ if (!mods.isDeferred) {
+ print(" = ")
+ if (rhs.isEmpty) print("_") else print(rhs)
+ }
+
+ case DefDef(mods, name, tparams, vparamss, tp, rhs) =>
+ printAnnotations(tree)
+ printModifiers(tree, mods)
+ print("def " + symName(tree, name))
+ printTypeParams(tparams); vparamss foreach printValueParams
+ printOpt(": ", tp); printOpt(" = ", rhs)
+
+ case TypeDef(mods, name, tparams, rhs) =>
+ if (mods hasFlag (PARAM | DEFERRED)) {
+ printAnnotations(tree)
+ printModifiers(tree, mods); print("type "); printParam(tree)
+ } else {
+ printAnnotations(tree)
+ printModifiers(tree, mods); print("type " + symName(tree, name))
+ printTypeParams(tparams); printOpt(" = ", rhs)
+ }
+
+ case LabelDef(name, params, rhs) =>
+ print(symName(tree, name)); printRow(params, "(", ",", ")"); printBlock(rhs)
+
+ case Import(expr, selectors) =>
+ // Is this selector remapping a name (i.e, {name1 => name2})
+ def isNotRemap(s: ImportSelector) : Boolean = (s.name == nme.WILDCARD || s.name == s.rename)
+ def selectorToString(s: ImportSelector): String = {
+ val from = quotedName(s.name)
+ if (isNotRemap(s)) from
+ else from + "=>" + quotedName(s.rename)
+ }
+ print("import "); print(backquotedPath(expr))
+ print(".")
+ selectors match {
+ case List(s) =>
+ // If there is just one selector and it is not remapping a name, no braces are needed
+ if (isNotRemap(s)) {
+ print(selectorToString(s))
+ } else {
+ print("{"); print(selectorToString(s)); print("}")
+ }
+ // If there is more than one selector braces are always needed
+ case many =>
+ print(many.map(selectorToString).mkString("{", ", ", "}"))
+ }
+
+ case DocDef(comment, definition) =>
+ print(comment.raw); println(); print(definition)
+
+ case Template(parents, self, body) =>
+ val currentOwner1 = currentOwner
+ if (tree.symbol != NoSymbol) currentOwner = tree.symbol.owner
+ printRow(parents, " with ")
+ if (!body.isEmpty) {
+ if (self.name != nme.WILDCARD) {
+ print(" { "); print(self.name); printOpt(": ", self.tpt); print(" => ")
+ } else if (!self.tpt.isEmpty) {
+ print(" { _ : "); print(self.tpt); print(" => ")
+ } else {
+ print(" {")
+ }
+ printColumn(body, "", ";", "}")
+ }
+ currentOwner = currentOwner1
+
+ case Block(stats, expr) =>
+ printColumn(stats ::: List(expr), "{", ";", "}")
+
+ case Match(selector, cases) =>
+ val selectorType1 = selectorType
+ selectorType = selector.tpe
+ print(selector); printColumn(cases, " match {", "", "}")
+ selectorType = selectorType1
+
+ case CaseDef(pat, guard, body) =>
+ print("case ")
+ def patConstr(pat: Tree): Tree = pat match {
+ case Apply(fn, args) => patConstr(fn)
+ case _ => pat
+ }
+ if (showOuterTests &&
+ needsOuterTest(
+ patConstr(pat).tpe.finalResultType, selectorType, currentOwner))
+ print("???")
+ print(pat); printOpt(" if ", guard)
+ print(" => "); print(body)
+
+ case Alternative(trees) =>
+ printRow(trees, "(", "| ", ")")
+
+ case Star(elem) =>
+ print("("); print(elem); print(")*")
+
+ case Bind(name, t) =>
+ print("("); print(symName(tree, name)); print(" @ "); print(t); print(")")
+
+ case UnApply(fun, args) =>
+ print(fun); print(" <unapply> "); printRow(args, "(", ", ", ")")
+
+ case ArrayValue(elemtpt, trees) =>
+ print("Array["); print(elemtpt); printRow(trees, "]{", ", ", "}")
+
+ case Function(vparams, body) =>
+ print("("); printValueParams(vparams); print(" => "); print(body); print(")")
+ if (settings.uniqid.value && tree.symbol != null) print("#"+tree.symbol.id)
+
+ case Assign(lhs, rhs) =>
+ print(lhs); print(" = "); print(rhs)
+
+ case AssignOrNamedArg(lhs, rhs) =>
+ print(lhs); print(" = "); print(rhs)
+
+ case If(cond, thenp, elsep) =>
+ print("if ("); print(cond); print(")"); indent; println()
+ print(thenp); undent
+ if (!elsep.isEmpty) {
+ println(); print("else"); indent; println(); print(elsep); undent
+ }
+
+ case Return(expr) =>
+ print("return "); print(expr)
+
+ case Try(block, catches, finalizer) =>
+ print("try "); printBlock(block)
+ if (!catches.isEmpty) printColumn(catches, " catch {", "", "}")
+ printOpt(" finally ", finalizer)
+
+ case Throw(expr) =>
+ print("throw "); print(expr)
+
+ case New(tpe) =>
+ print("new "); print(tpe)
+
+ case Typed(expr, tp) =>
+ print("("); print(expr); print(": "); print(tp); print(")")
+
+ case TypeApply(fun, targs) =>
+ print(fun); printRow(targs, "[", ", ", "]")
+
+ case Apply(fun, vargs) =>
+ print(fun); printRow(vargs, "(", ", ", ")")
+
+ case ApplyDynamic(qual, vargs) =>
+ print("<apply-dynamic>("); print(qual); print("#"); print(tree.symbol.nameString)
+ printRow(vargs, ", (", ", ", "))")
+
+ case Super(This(qual), mix) =>
+ if (!qual.isEmpty || tree.symbol != NoSymbol) print(symName(tree, qual) + ".")
+ print("super")
+ if (!mix.isEmpty)
+ print("[" + mix + "]")
+
+ case Super(qual, mix) =>
+ print(qual)
+ print(".super")
+ if (!mix.isEmpty)
+ print("[" + mix + "]")
+
+ case This(qual) =>
+ if (!qual.isEmpty) print(symName(tree, qual) + ".")
+ print("this")
+
+ case Select(qual @ New(tpe), name) if (!settings.debug.value) =>
+ print(qual)
+
+ case Select(qualifier, name) =>
+ print(backquotedPath(qualifier)); print("."); print(symName(tree, name))
+
+ case Ident(name) =>
+ print(symName(tree, name))
+
+ case Literal(x) =>
+ print(x.escapedStringValue)
+
+ case tt: TypeTree =>
+ if ((tree.tpe eq null) || (settings.Xprintpos.value && tt.original != null)) {
+ if (tt.original != null) { print("<type: "); print(tt.original); print(">") }
+ else print("<type ?>")
+ } else if ((tree.tpe.typeSymbol ne null) && tree.tpe.typeSymbol.isAnonymousClass) {
+ print(tree.tpe.typeSymbol.toString())
+ } else {
+ print(tree.tpe.toString())
+ }
+
+ case Annotated(Apply(Select(New(tpt), nme.CONSTRUCTOR), args), tree) =>
+ def printAnnot() {
+ print("@"); print(tpt)
+ if (!args.isEmpty)
+ printRow(args, "(", ",", ")")
+ }
+ if (tree.isType) { print(tree); print(" "); printAnnot() }
+ else { print(tree); print(": "); printAnnot() }
+
+ case SingletonTypeTree(ref) =>
+ print(ref); print(".type")
+
+ case SelectFromTypeTree(qualifier, selector) =>
+ print(qualifier); print("#"); print(symName(tree, selector))
+
+ case CompoundTypeTree(templ) =>
+ print(templ)
+
+ case AppliedTypeTree(tp, args) =>
+ print(tp); printRow(args, "[", ", ", "]")
+
+ case TypeBoundsTree(lo, hi) =>
+ printOpt(" >: ", lo); printOpt(" <: ", hi)
+
+ case ExistentialTypeTree(tpt, whereClauses) =>
+ print(tpt);
+ printColumn(whereClauses, " forSome { ", ";", "}")
+
+ case SelectFromArray(qualifier, name, _) =>
+ print(qualifier); print(".<arr>"); print(symName(tree, name))
+
+ case TypeTreeWithDeferredRefCheck() =>
+ print("<tree with deferred refcheck>")
+
+ case tree =>
+ print("<unknown tree of class "+tree.getClass+">")
+ }
+ if (settings.printtypes.value && tree.isTerm && !tree.isEmpty) {
+ print("{"); print(if (tree.tpe eq null) "<null>" else tree.tpe.toString()); print("}")
+ }
+ }
+
+ def print(tree: Tree) {
+ printPosition(tree)
+ printRaw(
+ //nsc if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.isInitialized) {
+ //nsc tree match {
+ //nsc case ClassDef(_, _, _, impl @ Template(ps, emptyValDef, body))
+ //nsc if (tree.symbol.thisSym != tree.symbol) =>
+ //nsc ClassDef(tree.symbol, Template(ps, ValDef(tree.symbol.thisSym), body))
+ //nsc case ClassDef(_, _, _, impl) => ClassDef(tree.symbol, impl)
+ //nsc case ModuleDef(_, _, impl) => ModuleDef(tree.symbol, impl)
+ //nsc case ValDef(_, _, _, rhs) => ValDef(tree.symbol, rhs)
+ //nsc case DefDef(_, _, _, vparamss, _, rhs) => DefDef(tree.symbol, vparamss, rhs)
+ //nsc case TypeDef(_, _, _, rhs) => TypeDef(tree.symbol, rhs)
+ //nsc case _ => tree
+ //nsc }
+ //nsc } else
+ tree)
+ }
+ }
+
+ def newTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer)
+ def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream))
+ def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter))
+
+ /** A writer that writes to the current Console and
+ * is sensitive to replacement of the Console's
+ * output stream.
+ */
+ object ConsoleWriter extends Writer {
+ override def write(str: String) { Console.print(str) }
+
+ def write(cbuf: Array[Char], off: Int, len: Int) {
+ write(new String(cbuf, off, len))
+ }
+
+ def close = { /* do nothing */ }
+ def flush = { /* do nothing */ }
+ }
+}
diff --git a/src/compiler/scala/reflect/common/Trees.scala b/src/compiler/scala/reflect/common/Trees.scala
new file mode 100644
index 0000000000..f7008d7a65
--- /dev/null
+++ b/src/compiler/scala/reflect/common/Trees.scala
@@ -0,0 +1,1823 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+import scala.collection.mutable.ListBuffer
+import Flags._
+import util.HashSet
+import java.io.{ PrintWriter, StringWriter }
+import Flags._
+
+//import scala.tools.nsc.util.{ FreshNameCreator, HashSet, SourceFile }
+
+trait Trees /*extends reflect.generic.Trees*/ { self: SymbolTable =>
+
+ type DocComment <: { def raw: String }
+
+ private[scala] var nodeCount = 0
+
+ object treeInfo extends {
+ val trees: Trees.this.type = self
+ } with TreeInfo
+
+ /** @param privateWithin the qualifier for a private (a type name)
+ * or tpnme.EMPTY, if none is given.
+ * @param annotations the annotations for the definition.
+ * <strong>Note:</strong> the typechecker drops these annotations,
+ * use the AnnotationInfo's (Symbol.annotations) in later phases.
+ */
+ case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position]) extends HasFlags {
+ /* Abstract types from HasFlags. */
+ type FlagsType = Long
+ type AccessBoundaryType = Name
+ type AnnotationType = Tree
+
+ def hasAccessBoundary = privateWithin != tpnme.EMPTY
+ def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask
+ def hasFlag(flag: Long) = (flag & flags) != 0L
+ def hasFlagsToString(mask: Long): String = flagsToString(
+ flags & mask,
+ if (hasAccessBoundary) privateWithin.toString else ""
+ )
+ def & (flag: Long): Modifiers = {
+ val flags1 = flags & flag
+ if (flags1 == flags) this
+ else Modifiers(flags1, privateWithin, annotations, positions)
+ }
+ def &~ (flag: Long): Modifiers = {
+ val flags1 = flags & (~flag)
+ if (flags1 == flags) this
+ else Modifiers(flags1, privateWithin, annotations, positions)
+ }
+ def | (flag: Long): Modifiers = {
+ val flags1 = flags | flag
+ if (flags1 == flags) this
+ else Modifiers(flags1, privateWithin, annotations, positions)
+ }
+ def withAnnotations(annots: List[Tree]) =
+ if (annots.isEmpty) this
+ else copy(annotations = annotations ::: annots)
+ def withPosition(flag: Long, position: Position) =
+ copy(positions = positions + (flag -> position))
+
+ override def toString = "Modifiers(%s, %s, %s)".format(hasFlagsToString(-1L), annotations mkString ", ", positions)
+ }
+
+ def Modifiers(flags: Long, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List(), Map.empty)
+ def Modifiers(flags: Long): Modifiers = Modifiers(flags, tpnme.EMPTY)
+
+ lazy val NoMods = Modifiers(0)
+
+ // ------ tree base classes --------------------------------------------------
+
+ /** The base class for all trees */
+ abstract class Tree extends Product {
+ val id = nodeCount
+ nodeCount += 1
+
+ private[this] var rawpos: Position = NoPosition
+
+ def pos = rawpos
+ def pos_=(pos: Position) = rawpos = pos
+ def setPos(pos: Position): this.type = { rawpos = pos; this }
+
+ private[this] var rawtpe: Type = _
+
+ def tpe = rawtpe
+ def tpe_=(t: Type) = rawtpe = t
+
+ /** Set tpe to give `tp` and return this.
+ */
+ def setType(tp: Type): this.type = { rawtpe = tp; this }
+
+ /** Like `setType`, but if this is a previously empty TypeTree
+ * that fact is remembered so that resetType will snap back.
+ */
+ def defineType(tp: Type): this.type = setType(tp)
+
+ def symbol: Symbol = null
+ def symbol_=(sym: Symbol) { throw new UnsupportedOperationException("symbol_= inapplicable for " + this) }
+ def setSymbol(sym: Symbol): this.type = { symbol = sym; this }
+
+ def hasSymbol = false
+ def isDef = false
+ def isEmpty = false
+
+ def hasSymbolWhich(f: Symbol => Boolean) = hasSymbol && f(symbol)
+
+ 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 DocDef(_, defn) => defn.isTerm
+ case _ => false
+ }
+
+ 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 DocDef(_, defn) => defn.isType
+ case _ => false
+ }
+
+ def isErroneous = (this.tpe ne null) && this.tpe.isErroneous
+ def isTyped = (this.tpe ne null) && !this.tpe.isErroneous
+
+ /** Apply `f' to each subtree */
+ def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(this) }
+
+ /** If 'pf' is defined for a given subtree, call super.traverse(pf(tree)),
+ * otherwise super.traverse(tree).
+ */
+ def foreachPartial(pf: PartialFunction[Tree, Tree]) { new ForeachPartialTreeTraverser(pf).traverse(this) }
+
+ /** Find all subtrees matching predicate `p' */
+ def filter(f: Tree => Boolean): List[Tree] = {
+ val ft = new FilterTreeTraverser(f)
+ ft.traverse(this)
+ ft.hits.toList
+ }
+
+ /** Returns optionally first tree (in a preorder traversal) which satisfies predicate `p',
+ * or None if none exists.
+ */
+ def find(p: Tree => Boolean): Option[Tree] = {
+ val ft = new FindTreeTraverser(p)
+ ft.traverse(this)
+ ft.result
+ }
+
+ def changeOwner(pairs: (Symbol, Symbol)*): Tree = {
+ pairs.foldLeft(this) { case (t, (oldOwner, newOwner)) =>
+ new ChangeOwnerTraverser(oldOwner, newOwner) apply t
+ }
+ }
+
+ /** Is there part of this tree which satisfies predicate `p'? */
+ def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty
+
+ def equalsStructure(that : Tree) = equalsStructure0(that)(_ eq _)
+ def equalsStructure0(that: Tree)(f: (Tree,Tree) => Boolean): Boolean =
+ f(this, that) || ((this.productArity == that.productArity) && {
+ def equals0(this0: Any, that0: Any): Boolean = (this0, that0) match {
+ case (x: Tree, y: Tree) => f(x, y) || (x equalsStructure0 y)(f)
+ case (xs: List[_], ys: List[_]) => (xs corresponds ys)(equals0)
+ case _ => this0 == that0
+ }
+ def compareOriginals() = (this, that) match {
+ case (x: TypeTree, y: TypeTree) if x.original != null && y.original != null =>
+ (x.original equalsStructure0 y.original)(f)
+ case _ =>
+ true
+ }
+
+ (this.productIterator zip that.productIterator forall { case (x, y) => equals0(x, y) }) && compareOriginals()
+ })
+
+ def shallowDuplicate: Tree = new ShallowDuplicator(this) transform this
+ def shortClass: String = this.getClass.getName split "[.$]" last
+
+ /** The direct child trees of this tree
+ * EmptyTrees are always omitted. Lists are collapsed.
+ */
+ def children: List[Tree] = {
+ def subtrees(x: Any): List[Tree] = x match {
+ case EmptyTree => Nil
+ case t: Tree => List(t)
+ case xs: List[_] => xs flatMap subtrees
+ case _ => Nil
+ }
+ productIterator.toList flatMap subtrees
+ }
+
+ /** Make a copy of this tree, keeping all attributes,
+ * except that all positions are focused (so nothing
+ * in this tree will be found when searching by position).
+ */
+ private[scala] def duplicate: this.type =
+ duplicateTree(this).asInstanceOf[this.type]
+
+ private[scala] def copyAttrs(tree: Tree): this.type = {
+ pos = tree.pos
+ tpe = tree.tpe
+ if (hasSymbol) symbol = tree.symbol
+ this
+ }
+
+ override def toString(): String = {
+ val buffer = new StringWriter()
+ val printer = newTreePrinter(new PrintWriter(buffer))
+ printer.print(this)
+ printer.flush()
+ buffer.toString
+ }
+
+ override def hashCode(): Int = System.identityHashCode(this)
+ override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
+ }
+
+ trait SymTree extends Tree {
+ override def hasSymbol = true
+ override var symbol: Symbol = NoSymbol
+ }
+
+ trait RefTree extends SymTree {
+ def name: Name
+ }
+
+ abstract class DefTree extends SymTree {
+ def name: Name
+ override def isDef = true
+ }
+
+ trait TermTree extends Tree
+
+ /** A tree for a type. Note that not all type trees implement
+ * this trait; in particular, Ident's are an exception. */
+ trait TypTree extends Tree
+
+// ----- tree node alternatives --------------------------------------
+
+ /** The empty tree */
+ case object EmptyTree extends TermTree {
+ super.tpe_=(NoType)
+ override def tpe_=(t: Type) =
+ if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>")
+ override def isEmpty = true
+ }
+
+ abstract class MemberDef extends DefTree {
+ def mods: Modifiers
+ def keyword: String = this match {
+ case TypeDef(_, _, _, _) => "type"
+ case ClassDef(mods, _, _, _) => if (mods hasFlag TRAIT) "trait" else "class"
+ case DefDef(_, _, _, _, _, _) => "def"
+ case ModuleDef(_, _, _) => "object"
+ case PackageDef(_, _) => "package"
+ case ValDef(mods, _, _, _) => if (mods.isMutable) "var" else "val"
+ case _ => ""
+ }
+ // final def hasFlag(mask: Long): Boolean = mods hasFlag mask
+ }
+
+ /** Package clause
+ */
+ case class PackageDef(pid: RefTree, stats: List[Tree])
+ extends MemberDef {
+ def name = pid.name
+ def mods = NoMods
+ }
+
+ abstract class ImplDef extends MemberDef {
+ def impl: Template
+ }
+
+ /** Class definition */
+ case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template)
+ extends ImplDef
+
+ /** Singleton object definition
+ */
+ case class ModuleDef(mods: Modifiers, name: TermName, impl: Template)
+ extends ImplDef
+
+ abstract class ValOrDefDef extends MemberDef {
+ def name: TermName
+ def tpt: Tree
+ def rhs: Tree
+ }
+
+ /** Value definition
+ */
+ case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef
+
+ /** Method definition
+ */
+ case class DefDef(mods: Modifiers, name: TermName, tparams: List[TypeDef],
+ vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef
+
+ /** Abstract type, type parameter, or type alias */
+ case class TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree)
+ extends MemberDef
+
+ /** <p>
+ * Labelled expression - the symbols in the array (must be Idents!)
+ * are those the label takes as argument
+ * </p>
+ * <p>
+ * The symbol that is given to the labeldef should have a MethodType
+ * (as if it were a nested function)
+ * </p>
+ * <p>
+ * Jumps are apply nodes attributed with label symbol, the arguments
+ * will get assigned to the idents.
+ * </p>
+ * <p>
+ * Note: on 2005-06-09 Martin, Iuli, Burak agreed to have forward
+ * jumps within a Block.
+ * </p>
+ */
+ case class LabelDef(name: TermName, params: List[Ident], rhs: Tree)
+ extends DefTree with TermTree
+
+
+ /** Import selector
+ *
+ * Representation of an imported name its optional rename and their optional positions
+ *
+ * @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
+ */
+ case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int)
+
+ /** Import clause
+ *
+ * @param expr
+ * @param selectors
+ */
+ case class Import(expr: Tree, selectors: List[ImportSelector])
+ extends SymTree
+ // 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.
+
+ /** Instantiation template of a class or trait
+ *
+ * @param parents
+ * @param body
+ */
+ case class Template(parents: List[Tree], self: ValDef, body: List[Tree])
+ extends SymTree {
+ // 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
+ // }
+ // System.err.println("TEMPLATE: " + parents)
+ }
+
+ /** Block of expressions (semicolon separated expressions) */
+ case class Block(stats: List[Tree], expr: Tree)
+ extends TermTree
+
+ /** Case clause in a pattern match, eliminated during explicitouter
+ * (except for occurrences in switch statements)
+ */
+ case class CaseDef(pat: Tree, guard: Tree, body: Tree)
+ extends Tree
+
+ /** Alternatives of patterns, eliminated by explicitouter, except for
+ * occurrences in encoded Switch stmt (=remaining Match(CaseDef(...))
+ */
+ case class Alternative(trees: List[Tree])
+ extends TermTree
+
+ /** Repetition of pattern, eliminated by explicitouter */
+ case class Star(elem: Tree)
+ extends TermTree
+
+ /** Bind of a variable to a rhs pattern, eliminated by explicitouter
+ *
+ * @param name
+ * @param body
+ */
+ case class Bind(name: Name, body: Tree)
+ extends DefTree
+
+ case class UnApply(fun: Tree, args: List[Tree])
+ extends TermTree
+
+ /** Array of expressions, needs to be translated in backend,
+ */
+ case class ArrayValue(elemtpt: Tree, elems: List[Tree])
+ extends TermTree
+
+ /** Anonymous function, eliminated by analyzer */
+ case class Function(vparams: List[ValDef], body: Tree)
+ extends TermTree with SymTree
+ // The symbol of a Function is a synthetic value of name nme.ANON_FUN_NAME
+ // It is the owner of the function's parameters.
+
+ /** Assignment */
+ case class Assign(lhs: Tree, rhs: Tree)
+ extends TermTree
+
+ /** Conditional expression */
+ case class If(cond: Tree, thenp: Tree, elsep: Tree)
+ extends TermTree
+
+ /** <p>
+ * Pattern matching expression (before explicitouter)
+ * Switch statements (after explicitouter)
+ * </p>
+ * <p>
+ * After explicitouter, cases will satisfy the following constraints:
+ * </p>
+ * <ul>
+ * <li>all guards are EmptyTree,</li>
+ * <li>all patterns will be either <code>Literal(Constant(x:Int))</code>
+ * or <code>Alternative(lit|...|lit)</code></li>
+ * <li>except for an "otherwise" branch, which has pattern
+ * <code>Ident(nme.WILDCARD)</code></li>
+ * </ul>
+ */
+ case class Match(selector: Tree, cases: List[CaseDef])
+ extends TermTree
+
+ /** Return expression */
+ case class Return(expr: Tree)
+ extends TermTree with SymTree
+ // The symbol of a Return node is the enclosing method.
+
+ case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree)
+ extends TermTree
+
+ /** Throw expression */
+ case class Throw(expr: Tree)
+ extends TermTree
+
+ /** Object instantiation
+ * One should always use factory method below to build a user level new.
+ *
+ * @param tpt a class type
+ */
+ case class New(tpt: Tree) extends TermTree
+
+ /** Type annotation, eliminated by explicit outer */
+ case class Typed(expr: Tree, tpt: Tree)
+ extends TermTree
+
+ // Martin to Sean: Should GenericApply/TypeApply/Apply not be SymTree's? After all,
+ // ApplyDynamic is a SymTree.
+ abstract class GenericApply extends TermTree {
+ val fun: Tree
+ val args: List[Tree]
+ }
+
+ /** Type application */
+ case class TypeApply(fun: Tree, args: List[Tree])
+ extends GenericApply {
+ override def symbol: Symbol = fun.symbol
+ override def symbol_=(sym: Symbol) { fun.symbol = sym }
+ }
+
+ /** Value application */
+ case class Apply(fun: Tree, args: List[Tree])
+ extends GenericApply {
+ override def symbol: Symbol = fun.symbol
+ override def symbol_=(sym: Symbol) { fun.symbol = sym }
+ }
+
+ /** Dynamic value application.
+ * In a dynamic application q.f(as)
+ * - q is stored in qual
+ * - as is stored in args
+ * - f is stored as the node's symbol field.
+ */
+ case class ApplyDynamic(qual: Tree, args: List[Tree])
+ extends TermTree with SymTree
+ // The symbol of an ApplyDynamic is the function symbol of `qual', or NoSymbol, if there is none.
+
+ /** Super reference, qual = corresponding this reference */
+ case class Super(qual: Tree, mix: TypeName) extends TermTree {
+ // The symbol of a Super is the class _from_ which the super reference is made.
+ // For instance in C.super(...), it would be C.
+ override def symbol: Symbol = qual.symbol
+ override def symbol_=(sym: Symbol) { qual.symbol = sym }
+ }
+
+ /** Self reference */
+ case class This(qual: TypeName)
+ extends TermTree with SymTree
+ // The symbol of a This is the class to which the this refers.
+ // For instance in C.this, it would be C.
+
+ /** Designator <qualifier> . <name> */
+ case class Select(qualifier: Tree, name: Name)
+ extends RefTree
+
+ /** Identifier <name> */
+ case class Ident(name: Name) extends RefTree { }
+
+ class BackQuotedIdent(name: Name) extends Ident(name)
+
+ /** Literal */
+ case class Literal(value: Constant)
+ extends TermTree {
+ assert(value ne null)
+ }
+
+ def Literal(value: Any): Literal =
+ Literal(Constant(value))
+
+ /** 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.
+ */
+ case class Annotated(annot: Tree, arg: Tree) extends Tree
+
+ /** Singleton type, eliminated by RefCheck */
+ case class SingletonTypeTree(ref: Tree)
+ extends TypTree
+
+ /** Type selection <qualifier> # <name>, eliminated by RefCheck */
+ case class SelectFromTypeTree(qualifier: Tree, name: TypeName)
+ extends TypTree with RefTree
+
+ /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */
+ case class CompoundTypeTree(templ: Template)
+ extends TypTree
+
+ /** Applied type <tpt> [ <args> ], eliminated by RefCheck */
+ case class AppliedTypeTree(tpt: Tree, args: List[Tree])
+ extends TypTree {
+ override def symbol: Symbol = tpt.symbol
+ override def symbol_=(sym: Symbol) { tpt.symbol = sym }
+ }
+
+ case class TypeBoundsTree(lo: Tree, hi: Tree)
+ extends TypTree
+
+ case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree])
+ extends TypTree
+
+ /** Array selection <qualifier> . <name> only used during erasure */
+ case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type)
+ extends TermTree with RefTree { }
+
+ /** 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
+ * <code>RefCheck</code>, where the arbitrary type trees are all replaced by
+ * TypeTree's. */
+ case class TypeTree() extends TypTree {
+ private var orig: Tree = null
+ private[Trees] var wasEmpty: Boolean = false
+
+ override def symbol = if (tpe == null) null else tpe.typeSymbol
+ override def isEmpty = (tpe eq null) || tpe == NoType
+
+ def original: Tree = orig
+ def setOriginal(tree: Tree): this.type = {
+ def followOriginal(t: Tree): Tree = t match {
+ case tt: TypeTree => followOriginal(tt.original)
+ case t => t
+ }
+
+ orig = followOriginal(tree); setPos(tree.pos);
+ this
+ }
+
+ override def defineType(tp: Type): this.type = {
+ wasEmpty = isEmpty
+ setType(tp)
+ }
+ }
+
+ def TypeTree(tp: Type): TypeTree = TypeTree() setType tp
+
+ /** Documented definition, eliminated by analyzer */
+ case class DocDef(comment: DocComment, definition: Tree)
+ extends Tree {
+ override def symbol: Symbol = definition.symbol
+ override def symbol_=(sym: Symbol) { definition.symbol = sym }
+ // sean: seems to be important to the IDE
+ override def isDef = definition.isDef
+ }
+
+ /** Either an assignment or a named argument. Only appears in argument lists,
+ * eliminated by typecheck (doTypedApply)
+ */
+ case class AssignOrNamedArg(lhs: Tree, rhs: Tree)
+ extends TermTree
+
+ case class Parens(args: List[Tree]) extends Tree // only used during parsing
+
+ /** emitted by typer, eliminated by refchecks */
+ case class TypeTreeWithDeferredRefCheck()(val check: () => TypeTree) extends TypTree
+ // ---- values and creators ---------------------------------------
+
+ /** @param sym the class symbol
+ * @return the implementation template
+ */
+ def ClassDef(sym: Symbol, impl: Template): ClassDef =
+ atPos(sym.pos) {
+ ClassDef(Modifiers(sym.flags),
+ sym.name.toTypeName,
+ sym.typeParams map TypeDef,
+ impl) setSymbol sym
+ }
+
+ /** Construct class definition with given class symbol, value parameters,
+ * supercall arguments and template body.
+ *
+ * @param sym the class symbol
+ * @param constrMods the modifiers for the class constructor, i.e. as in `class C private (...)'
+ * @param vparamss the value parameters -- if they have symbols they
+ * should be owned by `sym'
+ * @param argss the supercall arguments
+ * @param body the template statements without primary constructor
+ * and value parameter fields.
+ */
+ def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): ClassDef =
+ ClassDef(sym,
+ Template(sym.info.parents map TypeTree,
+ if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym),
+ constrMods, vparamss, argss, body, superPos))
+
+ /**
+ * @param sym the class symbol
+ * @param impl the implementation template
+ */
+ def ModuleDef(sym: Symbol, impl: Template): ModuleDef =
+ atPos(sym.pos) {
+ ModuleDef(Modifiers(sym.flags), sym.name, impl) setSymbol sym
+ }
+
+ def ValDef(sym: Symbol, rhs: Tree): ValDef =
+ atPos(sym.pos) {
+ ValDef(Modifiers(sym.flags), sym.name,
+ TypeTree(sym.tpe) setPos focusPos(sym.pos),
+ rhs) setSymbol sym
+ }
+
+ def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree)
+
+ object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) {
+ override def isEmpty = true
+ super.setPos(NoPosition)
+ override def setPos(pos: Position) = { assert(false); this }
+ }
+
+ def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef =
+ atPos(sym.pos) {
+ assert(sym != NoSymbol)
+ DefDef(Modifiers(sym.flags),
+ sym.name,
+ sym.typeParams map TypeDef,
+ vparamss,
+ TypeTree(sym.tpe.finalResultType) setPos focusPos(sym.pos),
+ rhs) setSymbol sym
+ }
+
+ def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef =
+ DefDef(sym, Modifiers(sym.flags), vparamss, rhs)
+
+ def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef =
+ DefDef(sym, mods, sym.paramss map (_.map(ValDef)), rhs)
+
+ def DefDef(sym: Symbol, rhs: Tree): DefDef =
+ DefDef(sym, Modifiers(sym.flags), rhs)
+
+ def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef = {
+ DefDef(sym, rhs(sym.info.paramss))
+ }
+
+ /** A TypeDef node which defines given `sym' with given tight hand side `rhs'. */
+ def TypeDef(sym: Symbol, rhs: Tree): TypeDef =
+ atPos(sym.pos) {
+ TypeDef(Modifiers(sym.flags), sym.name.toTypeName, sym.typeParams map TypeDef, rhs) setSymbol sym
+ }
+
+ /** A TypeDef node which defines abstract type or type parameter for given `sym' */
+ def TypeDef(sym: Symbol): TypeDef =
+ TypeDef(sym, TypeBoundsTree(TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi)))
+
+ def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef =
+ atPos(sym.pos) {
+ LabelDef(sym.name, params map Ident, rhs) setSymbol sym
+ }
+
+ /** Generates a template with constructor corresponding to
+ *
+ * constrmods (vparams1_) ... (vparams_n) preSuper { presupers }
+ * extends superclass(args_1) ... (args_n) with mixins { self => body }
+ *
+ * This gets translated to
+ *
+ * extends superclass with mixins { self =>
+ * presupers' // presupers without rhs
+ * vparamss // abstract fields corresponding to value parameters
+ * def <init>(vparamss) {
+ * presupers
+ * super.<init>(args)
+ * }
+ * body
+ * }
+ */
+ def Template(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): Template = {
+ /* Add constructor to template */
+
+ // create parameters for <init> as synthetic trees.
+ var vparamss1 =
+ vparamss map (vps => vps.map { vd =>
+ atPos(focusPos(vd.pos)) {
+ ValDef(
+ Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM | BYNAMEPARAM) | PARAM | PARAMACCESSOR) withAnnotations vd.mods.annotations,
+ vd.name, vd.tpt.duplicate, vd.rhs.duplicate)
+ }})
+ val (edefs, rest) = body span treeInfo.isEarlyDef
+ val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef
+ val (lvdefs, gvdefs) = evdefs map {
+ case vdef @ ValDef(mods, name, tpt, rhs) =>
+ val fld = treeCopy.ValDef(
+ vdef.duplicate, mods, name,
+ atPos(focusPos(vdef.pos)) { TypeTree() setOriginal tpt setPos focusPos(tpt.pos) }, // atPos in case
+ EmptyTree)
+ val local = treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs)
+ (local, fld)
+ } unzip
+
+ val constrs = {
+ if (constrMods hasFlag TRAIT) {
+ if (body forall treeInfo.isInterfaceMember) List()
+ else List(
+ atPos(wrappingPos(superPos, lvdefs)) (
+ DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(lvdefs, Literal(())))))
+ } else {
+ // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section
+ if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit)
+ vparamss1 = List() :: vparamss1;
+ val superRef: Tree = atPos(superPos) {
+ Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR)
+ }
+ val superCall = (superRef /: argss) (Apply)
+ List(
+ atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) (
+ DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(())))))
+ }
+ }
+ // println("typed template, gvdefs = "+gvdefs+", parents = "+parents+", constrs = "+constrs)
+ constrs foreach (ensureNonOverlapping(_, parents ::: gvdefs))
+ // vparamss2 are used as field definitions for the class. remove defaults
+ val vparamss2 = vparamss map (vps => vps map { vd =>
+ treeCopy.ValDef(vd, vd.mods &~ DEFAULTPARAM, vd.name, vd.tpt, EmptyTree)
+ })
+ Template(parents, self, gvdefs ::: vparamss2.flatten ::: constrs ::: etdefs ::: rest)
+ }
+
+ /** casedef shorthand */
+ def CaseDef(pat: Tree, body: Tree): CaseDef = CaseDef(pat, EmptyTree, body)
+
+ def Bind(sym: Symbol, body: Tree): Bind =
+ Bind(sym.name, body) setSymbol sym
+
+
+ /** 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 = {
+ assert(!argss.isEmpty)
+ val superRef: Tree = Select(New(tpt), nme.CONSTRUCTOR)
+ (superRef /: argss) (Apply)
+ }
+
+ def Apply(sym: Symbol, args: Tree*): Tree =
+ Apply(Ident(sym), args.toList)
+
+ def Super(sym: Symbol, mix: TypeName): Tree = Super(This(sym), mix)
+
+ def This(sym: Symbol): Tree = This(sym.name.toTypeName) setSymbol sym
+
+ def Select(qualifier: Tree, sym: Symbol): Select =
+ Select(qualifier, sym.name) setSymbol sym
+
+ def Ident(sym: Symbol): Ident =
+ Ident(sym.name) setSymbol sym
+
+ /** Block factory that flattens directly nested blocks.
+ */
+ def Block(stats: Tree*): Block = stats match {
+ case Seq(b @ Block(_, _)) => b
+ case Seq(stat) => Block(stats.toList, Literal(Constant(())))
+ case Seq(_, rest @ _*) => Block(stats.init.toList, stats.last)
+ }
+
+// ----- subconstructors --------------------------------------------
+
+ class ApplyToImplicitArgs(fun: Tree, args: List[Tree]) extends Apply(fun, args)
+
+ class ApplyImplicitView(fun: Tree, args: List[Tree]) extends Apply(fun, args)
+
+// ------ traversers, copiers, and transformers ---------------------------------------------
+
+ val treeCopy = new LazyTreeCopier()
+
+ class Traverser {
+ protected var currentOwner: Symbol = definitions.RootClass
+ def traverse(tree: Tree): Unit = tree match {
+ case EmptyTree =>
+ ;
+ case PackageDef(pid, stats) =>
+ traverse(pid)
+ atOwner(tree.symbol.moduleClass) {
+ traverseTrees(stats)
+ }
+ case ClassDef(mods, name, tparams, impl) =>
+ atOwner(tree.symbol) {
+ traverseTrees(mods.annotations); traverseTrees(tparams); traverse(impl)
+ }
+ case ModuleDef(mods, name, impl) =>
+ atOwner(tree.symbol.moduleClass) {
+ traverseTrees(mods.annotations); traverse(impl)
+ }
+ case ValDef(mods, name, tpt, rhs) =>
+ atOwner(tree.symbol) {
+ traverseTrees(mods.annotations); traverse(tpt); traverse(rhs)
+ }
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ atOwner(tree.symbol) {
+ traverseTrees(mods.annotations); traverseTrees(tparams); traverseTreess(vparamss); traverse(tpt); traverse(rhs)
+ }
+ case TypeDef(mods, name, tparams, rhs) =>
+ atOwner(tree.symbol) {
+ traverseTrees(mods.annotations); traverseTrees(tparams); traverse(rhs)
+ }
+ case LabelDef(name, params, rhs) =>
+ traverseTrees(params); traverse(rhs)
+ case Import(expr, selectors) =>
+ traverse(expr)
+ case Annotated(annot, arg) =>
+ traverse(annot); traverse(arg)
+ case Template(parents, self, body) =>
+ traverseTrees(parents)
+ if (!self.isEmpty) traverse(self)
+ traverseStats(body, tree.symbol)
+ case Block(stats, expr) =>
+ traverseTrees(stats); traverse(expr)
+ case CaseDef(pat, guard, body) =>
+ traverse(pat); traverse(guard); traverse(body)
+ case Alternative(trees) =>
+ traverseTrees(trees)
+ case Star(elem) =>
+ traverse(elem)
+ case Bind(name, body) =>
+ traverse(body)
+ case UnApply(fun, args) =>
+ traverse(fun); traverseTrees(args)
+ case ArrayValue(elemtpt, trees) =>
+ traverse(elemtpt); traverseTrees(trees)
+ case Function(vparams, body) =>
+ atOwner(tree.symbol) {
+ traverseTrees(vparams); traverse(body)
+ }
+ case Assign(lhs, rhs) =>
+ traverse(lhs); traverse(rhs)
+ case If(cond, thenp, elsep) =>
+ traverse(cond); traverse(thenp); traverse(elsep)
+ case Match(selector, cases) =>
+ traverse(selector); traverseTrees(cases)
+ case Return(expr) =>
+ traverse(expr)
+ case Try(block, catches, finalizer) =>
+ traverse(block); traverseTrees(catches); traverse(finalizer)
+ case Throw(expr) =>
+ traverse(expr)
+ case New(tpt) =>
+ traverse(tpt)
+ case Typed(expr, tpt) =>
+ traverse(expr); traverse(tpt)
+ case TypeApply(fun, args) =>
+ traverse(fun); traverseTrees(args)
+ case Apply(fun, args) =>
+ traverse(fun); traverseTrees(args)
+ case ApplyDynamic(qual, args) =>
+ traverse(qual); traverseTrees(args)
+ case Super(qual, _) =>
+ traverse(qual)
+ case This(_) =>
+ ;
+ case Select(qualifier, selector) =>
+ traverse(qualifier)
+ case Ident(_) =>
+ ;
+ case Literal(_) =>
+ ;
+ case TypeTree() =>
+ ;
+ case SingletonTypeTree(ref) =>
+ traverse(ref)
+ case SelectFromTypeTree(qualifier, selector) =>
+ traverse(qualifier)
+ case CompoundTypeTree(templ) =>
+ traverse(templ)
+ case AppliedTypeTree(tpt, args) =>
+ traverse(tpt); traverseTrees(args)
+ case TypeBoundsTree(lo, hi) =>
+ traverse(lo); traverse(hi)
+ case ExistentialTypeTree(tpt, whereClauses) =>
+ traverse(tpt); traverseTrees(whereClauses)
+ case SelectFromArray(qualifier, selector, erasure) =>
+ traverse(qualifier)
+ case AssignOrNamedArg(lhs, rhs) =>
+ traverse(lhs); traverse(rhs)
+ case DocDef(comment, definition) =>
+ traverse(definition)
+ case Parens(ts) =>
+ traverseTrees(ts)
+ case TypeTreeWithDeferredRefCheck() => // TODO: should we traverse the wrapped tree?
+ // (and rewrap the result? how to update the deferred check? would need to store wrapped tree instead of returning it from check)
+ }
+
+ def traverseTrees(trees: List[Tree]) {
+ trees foreach traverse
+ }
+ def traverseTreess(treess: List[List[Tree]]) {
+ treess foreach traverseTrees
+ }
+ def traverseStats(stats: List[Tree], exprOwner: Symbol) {
+ stats foreach (stat =>
+ if (exprOwner != currentOwner) atOwner(exprOwner)(traverse(stat))
+ else traverse(stat)
+ )
+ }
+
+ def atOwner(owner: Symbol)(traverse: => Unit) {
+ val prevOwner = currentOwner
+ currentOwner = owner
+ traverse
+ currentOwner = prevOwner
+ }
+
+ /** Leave apply available in the generic traverser to do something else.
+ */
+ def apply[T <: Tree](tree: T): T = { traverse(tree); tree }
+ }
+
+ abstract class TreeCopier {
+ def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef
+ def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]): PackageDef
+ def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef
+ def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef
+ def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef
+ def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef
+ def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef
+ def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import
+ def DocDef(tree: Tree, comment: DocComment, definition: Tree): DocDef
+ def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template
+ def Block(tree: Tree, stats: List[Tree], expr: Tree): Block
+ def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef
+ def Alternative(tree: Tree, trees: List[Tree]): Alternative
+ 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
+ def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If
+ def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match
+ def Return(tree: Tree, expr: Tree): Return
+ def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try
+ def Throw(tree: Tree, expr: Tree): Throw
+ def New(tree: Tree, tpt: Tree): New
+ def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed
+ def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply
+ def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply
+ def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]): ApplyDynamic
+ def Super(tree: Tree, qual: Tree, mix: TypeName): Super
+ def This(tree: Tree, qual: Name): This
+ def Select(tree: Tree, qualifier: Tree, selector: Name): Select
+ def Ident(tree: Tree, name: Name): Ident
+ def Literal(tree: Tree, value: Constant): Literal
+ def TypeTree(tree: Tree): TypeTree
+ def TypeTreeWithDeferredRefCheck(tree: Tree): TypeTreeWithDeferredRefCheck
+ def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated
+ def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree
+ def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree
+ def CompoundTypeTree(tree: Tree, templ: Template): CompoundTypeTree
+ def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree
+ def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree
+ def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree
+ def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type): SelectFromArray
+ }
+
+ class StrictTreeCopier extends TreeCopier {
+ def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) =
+ new ClassDef(mods, name.toTypeName, tparams, impl).copyAttrs(tree)
+ def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) =
+ new PackageDef(pid, stats).copyAttrs(tree)
+ def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) =
+ new ModuleDef(mods, name, impl).copyAttrs(tree)
+ def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) =
+ new ValDef(mods, name, tpt, rhs).copyAttrs(tree)
+ def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) =
+ new DefDef(mods, name, tparams, vparamss, tpt, rhs).copyAttrs(tree)
+ def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) =
+ new TypeDef(mods, name.toTypeName, tparams, rhs).copyAttrs(tree)
+ def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) =
+ new LabelDef(name, params, rhs).copyAttrs(tree)
+ def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) =
+ new Import(expr, selectors).copyAttrs(tree)
+ def DocDef(tree: Tree, comment: DocComment, definition: Tree) =
+ new DocDef(comment, definition).copyAttrs(tree)
+ def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) =
+ new Template(parents, self, body).copyAttrs(tree)
+ def Block(tree: Tree, stats: List[Tree], expr: Tree) =
+ new Block(stats, expr).copyAttrs(tree)
+ def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) =
+ new CaseDef(pat, guard, body).copyAttrs(tree)
+ def Alternative(tree: Tree, trees: List[Tree]) =
+ new Alternative(trees).copyAttrs(tree)
+ def Star(tree: Tree, elem: Tree) =
+ new Star(elem).copyAttrs(tree)
+ def Bind(tree: Tree, name: Name, body: Tree) =
+ new Bind(name, body).copyAttrs(tree)
+ def UnApply(tree: Tree, fun: Tree, args: List[Tree]) =
+ new UnApply(fun, args).copyAttrs(tree)
+ def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) =
+ new ArrayValue(elemtpt, trees).copyAttrs(tree)
+ def Function(tree: Tree, vparams: List[ValDef], body: Tree) =
+ new Function(vparams, body).copyAttrs(tree)
+ def Assign(tree: Tree, lhs: Tree, rhs: Tree) =
+ new Assign(lhs, rhs).copyAttrs(tree)
+ def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) =
+ new AssignOrNamedArg(lhs, rhs).copyAttrs(tree)
+ def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) =
+ new If(cond, thenp, elsep).copyAttrs(tree)
+ def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) =
+ new Match(selector, cases).copyAttrs(tree)
+ def Return(tree: Tree, expr: Tree) =
+ new Return(expr).copyAttrs(tree)
+ def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) =
+ new Try(block, catches, finalizer).copyAttrs(tree)
+ def Throw(tree: Tree, expr: Tree) =
+ new Throw(expr).copyAttrs(tree)
+ def New(tree: Tree, tpt: Tree) =
+ new New(tpt).copyAttrs(tree)
+ def Typed(tree: Tree, expr: Tree, tpt: Tree) =
+ new Typed(expr, tpt).copyAttrs(tree)
+ def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) =
+ new TypeApply(fun, args).copyAttrs(tree)
+ def Apply(tree: Tree, fun: Tree, args: List[Tree]) =
+ (tree match {
+ case _: ApplyToImplicitArgs => new ApplyToImplicitArgs(fun, args)
+ case _: ApplyImplicitView => new ApplyImplicitView(fun, args)
+ case _ => new Apply(fun, args)
+ }).copyAttrs(tree)
+ def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) =
+ new ApplyDynamic(qual, args).copyAttrs(tree)
+ def Super(tree: Tree, qual: Tree, mix: TypeName) =
+ new Super(qual, mix).copyAttrs(tree)
+ def This(tree: Tree, qual: Name) =
+ new This(qual.toTypeName).copyAttrs(tree)
+ def Select(tree: Tree, qualifier: Tree, selector: Name) =
+ new Select(qualifier, selector).copyAttrs(tree)
+ def Ident(tree: Tree, name: Name) =
+ new Ident(name).copyAttrs(tree)
+ def Literal(tree: Tree, value: Constant) =
+ new Literal(value).copyAttrs(tree)
+ def TypeTree(tree: Tree) =
+ new TypeTree().copyAttrs(tree)
+ def TypeTreeWithDeferredRefCheck(tree: Tree) = tree match {
+ case dc@TypeTreeWithDeferredRefCheck() => new TypeTreeWithDeferredRefCheck()(dc.check).copyAttrs(tree)
+ }
+ def Annotated(tree: Tree, annot: Tree, arg: Tree) =
+ new Annotated(annot, arg).copyAttrs(tree)
+ def SingletonTypeTree(tree: Tree, ref: Tree) =
+ new SingletonTypeTree(ref).copyAttrs(tree)
+ def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) =
+ new SelectFromTypeTree(qualifier, selector.toTypeName).copyAttrs(tree)
+ def CompoundTypeTree(tree: Tree, templ: Template) =
+ new CompoundTypeTree(templ).copyAttrs(tree)
+ def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) =
+ new AppliedTypeTree(tpt, args).copyAttrs(tree)
+ def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) =
+ new TypeBoundsTree(lo, hi).copyAttrs(tree)
+ def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) =
+ new ExistentialTypeTree(tpt, whereClauses).copyAttrs(tree)
+ def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) =
+ new SelectFromArray(qualifier, selector, erasure).copyAttrs(tree)
+ }
+
+ class LazyTreeCopier(treeCopy: TreeCopier) extends TreeCopier {
+ def this() = this(new StrictTreeCopier)
+ def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) = tree match {
+ case t @ ClassDef(mods0, name0, tparams0, impl0)
+ if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (impl0 == impl) => t
+ case _ => treeCopy.ClassDef(tree, mods, name, tparams, impl)
+ }
+ def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) = tree match {
+ case t @ PackageDef(pid0, stats0)
+ if (pid0 == pid) && (stats0 == stats) => t
+ case _ => treeCopy.PackageDef(tree, pid, stats)
+ }
+ def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = tree match {
+ case t @ ModuleDef(mods0, name0, impl0)
+ if (mods0 == mods) && (name0 == name) && (impl0 == impl) => t
+ case _ => treeCopy.ModuleDef(tree, mods, name, impl)
+ }
+ def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) = tree match {
+ case t @ ValDef(mods0, name0, tpt0, rhs0)
+ if (mods0 == mods) && (name0 == name) && (tpt0 == tpt) && (rhs0 == rhs) => t
+ case _ => treeCopy.ValDef(tree, mods, name, tpt, rhs)
+ }
+ def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = tree match {
+ case t @ DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0)
+ if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) &&
+ (vparamss0 == vparamss) && (tpt0 == tpt) && (rhs == rhs0) => t
+ case _ => treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs)
+ }
+ def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) = tree match {
+ case t @ TypeDef(mods0, name0, tparams0, rhs0)
+ if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (rhs0 == rhs) => t
+ case _ => treeCopy.TypeDef(tree, mods, name, tparams, rhs)
+ }
+ def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = tree match {
+ case t @ LabelDef(name0, params0, rhs0)
+ if (name0 == name) && (params0 == params) && (rhs0 == rhs) => t
+ case _ => treeCopy.LabelDef(tree, name, params, rhs)
+ }
+ def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = tree match {
+ case t @ Import(expr0, selectors0)
+ if (expr0 == expr) && (selectors0 == selectors) => t
+ case _ => treeCopy.Import(tree, expr, selectors)
+ }
+ def DocDef(tree: Tree, comment: DocComment, definition: Tree) = tree match {
+ case t @ DocDef(comment0, definition0)
+ if (comment0 == comment) && (definition0 == definition) => t
+ case _ => treeCopy.DocDef(tree, comment, definition)
+ }
+ def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) = tree match {
+ case t @ Template(parents0, self0, body0)
+ if (parents0 == parents) && (self0 == self) && (body0 == body) => t
+ case _ => treeCopy.Template(tree, parents, self, body)
+ }
+ def Block(tree: Tree, stats: List[Tree], expr: Tree) = tree match {
+ case t @ Block(stats0, expr0)
+ if ((stats0 == stats) && (expr0 == expr)) => t
+ case _ => treeCopy.Block(tree, stats, expr)
+ }
+ def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = tree match {
+ case t @ CaseDef(pat0, guard0, body0)
+ if (pat0 == pat) && (guard0 == guard) && (body0 == body) => t
+ case _ => treeCopy.CaseDef(tree, pat, guard, body)
+ }
+ def Alternative(tree: Tree, trees: List[Tree]) = tree match {
+ case t @ Alternative(trees0)
+ if trees0 == trees => t
+ case _ => treeCopy.Alternative(tree, trees)
+ }
+ def Star(tree: Tree, elem: Tree) = tree match {
+ case t @ Star(elem0)
+ if elem0 == elem => t
+ case _ => treeCopy.Star(tree, elem)
+ }
+ def Bind(tree: Tree, name: Name, body: Tree) = tree match {
+ case t @ Bind(name0, body0)
+ if (name0 == name) && (body0 == body) => t
+ case _ => treeCopy.Bind(tree, name, body)
+ }
+ def UnApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
+ case t @ UnApply(fun0, args0)
+ if (fun0 == fun) && (args0 == args) => t
+ case _ => treeCopy.UnApply(tree, fun, args)
+ }
+ def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) = tree match {
+ case t @ ArrayValue(elemtpt0, trees0)
+ if (elemtpt0 == elemtpt) && (trees0 == trees) => t
+ case _ => treeCopy.ArrayValue(tree, elemtpt, trees)
+ }
+ def Function(tree: Tree, vparams: List[ValDef], body: Tree) = tree match {
+ case t @ Function(vparams0, body0)
+ if (vparams0 == vparams) && (body0 == body) => t
+ case _ => treeCopy.Function(tree, vparams, body)
+ }
+ def Assign(tree: Tree, lhs: Tree, rhs: Tree) = tree match {
+ case t @ Assign(lhs0, rhs0)
+ if (lhs0 == lhs) && (rhs0 == rhs) => t
+ case _ => treeCopy.Assign(tree, lhs, rhs)
+ }
+ def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = tree match {
+ case t @ AssignOrNamedArg(lhs0, rhs0)
+ if (lhs0 == lhs) && (rhs0 == rhs) => t
+ case _ => treeCopy.AssignOrNamedArg(tree, lhs, rhs)
+ }
+ def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = tree match {
+ case t @ If(cond0, thenp0, elsep0)
+ if (cond0 == cond) && (thenp0 == thenp) && (elsep0 == elsep) => t
+ case _ => treeCopy.If(tree, cond, thenp, elsep)
+ }
+ def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = tree match {
+ case t @ Match(selector0, cases0)
+ if (selector0 == selector) && (cases0 == cases) => t
+ case _ => treeCopy.Match(tree, selector, cases)
+ }
+ def Return(tree: Tree, expr: Tree) = tree match {
+ case t @ Return(expr0)
+ if expr0 == expr => t
+ case _ => treeCopy.Return(tree, expr)
+ }
+ def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = tree match {
+ case t @ Try(block0, catches0, finalizer0)
+ if (block0 == block) && (catches0 == catches) && (finalizer0 == finalizer) => t
+ case _ => treeCopy.Try(tree, block, catches, finalizer)
+ }
+ def Throw(tree: Tree, expr: Tree) = tree match {
+ case t @ Throw(expr0)
+ if expr0 == expr => t
+ case _ => treeCopy.Throw(tree, expr)
+ }
+ def New(tree: Tree, tpt: Tree) = tree match {
+ case t @ New(tpt0)
+ if tpt0 == tpt => t
+ case _ => treeCopy.New(tree, tpt)
+ }
+ def Typed(tree: Tree, expr: Tree, tpt: Tree) = tree match {
+ case t @ Typed(expr0, tpt0)
+ if (expr0 == expr) && (tpt0 == tpt) => t
+ case _ => treeCopy.Typed(tree, expr, tpt)
+ }
+ def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
+ case t @ TypeApply(fun0, args0)
+ if (fun0 == fun) && (args0 == args) => t
+ case _ => treeCopy.TypeApply(tree, fun, args)
+ }
+ def Apply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
+ case t @ Apply(fun0, args0)
+ if (fun0 == fun) && (args0 == args) => t
+ case _ => treeCopy.Apply(tree, fun, args)
+ }
+ def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = tree match {
+ case t @ ApplyDynamic(qual0, args0)
+ if (qual0 == qual) && (args0 == args) => t
+ case _ => treeCopy.ApplyDynamic(tree, qual, args)
+ }
+ def Super(tree: Tree, qual: Tree, mix: TypeName) = tree match {
+ case t @ Super(qual0, mix0)
+ if (qual0 == qual) && (mix0 == mix) => t
+ case _ => treeCopy.Super(tree, qual, mix)
+ }
+ def This(tree: Tree, qual: Name) = tree match {
+ case t @ This(qual0)
+ if qual0 == qual => t
+ case _ => treeCopy.This(tree, qual)
+ }
+ def Select(tree: Tree, qualifier: Tree, selector: Name) = tree match {
+ case t @ Select(qualifier0, selector0)
+ if (qualifier0 == qualifier) && (selector0 == selector) => t
+ case _ => treeCopy.Select(tree, qualifier, selector)
+ }
+ def Ident(tree: Tree, name: Name) = tree match {
+ case t @ Ident(name0)
+ if name0 == name => t
+ case _ => treeCopy.Ident(tree, name)
+ }
+ def Literal(tree: Tree, value: Constant) = tree match {
+ case t @ Literal(value0)
+ if value0 == value => t
+ case _ => treeCopy.Literal(tree, value)
+ }
+ def TypeTree(tree: Tree) = tree match {
+ case t @ TypeTree() => t
+ case _ => treeCopy.TypeTree(tree)
+ }
+ def TypeTreeWithDeferredRefCheck(tree: Tree) = tree match {
+ case t @ TypeTreeWithDeferredRefCheck() => t
+ case _ => treeCopy.TypeTreeWithDeferredRefCheck(tree)
+ }
+ def Annotated(tree: Tree, annot: Tree, arg: Tree) = tree match {
+ case t @ Annotated(annot0, arg0)
+ if (annot0==annot) => t
+ case _ => treeCopy.Annotated(tree, annot, arg)
+ }
+ def SingletonTypeTree(tree: Tree, ref: Tree) = tree match {
+ case t @ SingletonTypeTree(ref0)
+ if ref0 == ref => t
+ case _ => treeCopy.SingletonTypeTree(tree, ref)
+ }
+ def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = tree match {
+ case t @ SelectFromTypeTree(qualifier0, selector0)
+ if (qualifier0 == qualifier) && (selector0 == selector) => t
+ case _ => treeCopy.SelectFromTypeTree(tree, qualifier, selector)
+ }
+ def CompoundTypeTree(tree: Tree, templ: Template) = tree match {
+ case t @ CompoundTypeTree(templ0)
+ if templ0 == templ => t
+ case _ => treeCopy.CompoundTypeTree(tree, templ)
+ }
+ def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = tree match {
+ case t @ AppliedTypeTree(tpt0, args0)
+ if (tpt0 == tpt) && (args0 == args) => t
+ case _ => treeCopy.AppliedTypeTree(tree, tpt, args)
+ }
+ def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = tree match {
+ case t @ TypeBoundsTree(lo0, hi0)
+ if (lo0 == lo) && (hi0 == hi) => t
+ case _ => treeCopy.TypeBoundsTree(tree, lo, hi)
+ }
+ def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = tree match {
+ case t @ ExistentialTypeTree(tpt0, whereClauses0)
+ if (tpt0 == tpt) && (whereClauses0 == whereClauses) => t
+ case _ => treeCopy.ExistentialTypeTree(tree, tpt, whereClauses)
+ }
+ def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) = tree match {
+ case t @ SelectFromArray(qualifier0, selector0, _)
+ if (qualifier0 == qualifier) && (selector0 == selector) => t
+ case _ => treeCopy.SelectFromArray(tree, qualifier, selector, erasure)
+ }
+ }
+
+ abstract class Transformer {
+ val treeCopy: TreeCopier = new LazyTreeCopier
+ protected var currentOwner: Symbol = definitions.RootClass
+ protected def currentMethod = currentOwner.enclMethod
+ protected def currentClass = currentOwner.enclClass
+ protected def currentPackage = currentOwner.toplevelClass.owner
+ def transform(tree: Tree): Tree = tree match {
+ case EmptyTree =>
+ tree
+ case PackageDef(pid, stats) =>
+ treeCopy.PackageDef(
+ tree, transform(pid).asInstanceOf[RefTree],
+ atOwner(tree.symbol.moduleClass) {
+ transformStats(stats, currentOwner)
+ }
+ )
+ case ClassDef(mods, name, tparams, impl) =>
+ atOwner(tree.symbol) {
+ treeCopy.ClassDef(tree, transformModifiers(mods), name,
+ transformTypeDefs(tparams), transformTemplate(impl))
+ }
+ case ModuleDef(mods, name, impl) =>
+ atOwner(tree.symbol.moduleClass) {
+ treeCopy.ModuleDef(tree, transformModifiers(mods),
+ name, transformTemplate(impl))
+ }
+ case ValDef(mods, name, tpt, rhs) =>
+ atOwner(tree.symbol) {
+ treeCopy.ValDef(tree, transformModifiers(mods),
+ name, transform(tpt), transform(rhs))
+ }
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ atOwner(tree.symbol) {
+ treeCopy.DefDef(tree, transformModifiers(mods), name,
+ transformTypeDefs(tparams), transformValDefss(vparamss),
+ transform(tpt), transform(rhs))
+ }
+ case TypeDef(mods, name, tparams, rhs) =>
+ atOwner(tree.symbol) {
+ treeCopy.TypeDef(tree, transformModifiers(mods), name,
+ transformTypeDefs(tparams), transform(rhs))
+ }
+ case LabelDef(name, params, rhs) =>
+ treeCopy.LabelDef(tree, name, transformIdents(params), transform(rhs)) //bq: Martin, once, atOwner(...) works, also change `LamdaLifter.proxy'
+ case Import(expr, selectors) =>
+ treeCopy.Import(tree, transform(expr), selectors)
+ case DocDef(comment, definition) =>
+ treeCopy.DocDef(tree, comment, transform(definition))
+ case Template(parents, self, body) =>
+ treeCopy.Template(tree, transformTrees(parents), transformValDef(self), transformStats(body, tree.symbol))
+ case Block(stats, expr) =>
+ treeCopy.Block(tree, transformStats(stats, currentOwner), transform(expr))
+ case CaseDef(pat, guard, body) =>
+ treeCopy.CaseDef(tree, transform(pat), transform(guard), transform(body))
+ case Alternative(trees) =>
+ treeCopy.Alternative(tree, transformTrees(trees))
+ case Star(elem) =>
+ treeCopy.Star(tree, transform(elem))
+ case Bind(name, body) =>
+ treeCopy.Bind(tree, name, transform(body))
+ case UnApply(fun, args) =>
+ treeCopy.UnApply(tree, fun, transformTrees(args)) // bq: see test/.../unapplyContexts2.scala
+ case ArrayValue(elemtpt, trees) =>
+ treeCopy.ArrayValue(tree, transform(elemtpt), transformTrees(trees))
+ case Function(vparams, body) =>
+ atOwner(tree.symbol) {
+ treeCopy.Function(tree, transformValDefs(vparams), transform(body))
+ }
+ case Assign(lhs, rhs) =>
+ treeCopy.Assign(tree, transform(lhs), transform(rhs))
+ case AssignOrNamedArg(lhs, rhs) =>
+ treeCopy.AssignOrNamedArg(tree, transform(lhs), transform(rhs))
+ case If(cond, thenp, elsep) =>
+ treeCopy.If(tree, transform(cond), transform(thenp), transform(elsep))
+ case Match(selector, cases) =>
+ treeCopy.Match(tree, transform(selector), transformCaseDefs(cases))
+ case Return(expr) =>
+ treeCopy.Return(tree, transform(expr))
+ case Try(block, catches, finalizer) =>
+ treeCopy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer))
+ case Throw(expr) =>
+ treeCopy.Throw(tree, transform(expr))
+ case New(tpt) =>
+ treeCopy.New(tree, transform(tpt))
+ case Typed(expr, tpt) =>
+ treeCopy.Typed(tree, transform(expr), transform(tpt))
+ case TypeApply(fun, args) =>
+ treeCopy.TypeApply(tree, transform(fun), transformTrees(args))
+ case Apply(fun, args) =>
+ treeCopy.Apply(tree, transform(fun), transformTrees(args))
+ case ApplyDynamic(qual, args) =>
+ treeCopy.ApplyDynamic(tree, transform(qual), transformTrees(args))
+ case Super(qual, mix) =>
+ treeCopy.Super(tree, transform(qual), mix)
+ case This(qual) =>
+ treeCopy.This(tree, qual)
+ case Select(qualifier, selector) =>
+ treeCopy.Select(tree, transform(qualifier), selector)
+ case Ident(name) =>
+ treeCopy.Ident(tree, name)
+ case Literal(value) =>
+ treeCopy.Literal(tree, value)
+ case TypeTree() =>
+ treeCopy.TypeTree(tree)
+ case TypeTreeWithDeferredRefCheck() =>
+ treeCopy.TypeTreeWithDeferredRefCheck(tree)
+ case Annotated(annot, arg) =>
+ treeCopy.Annotated(tree, transform(annot), transform(arg))
+ case SingletonTypeTree(ref) =>
+ treeCopy.SingletonTypeTree(tree, transform(ref))
+ case SelectFromTypeTree(qualifier, selector) =>
+ treeCopy.SelectFromTypeTree(tree, transform(qualifier), selector)
+ case CompoundTypeTree(templ) =>
+ treeCopy.CompoundTypeTree(tree, transformTemplate(templ))
+ case AppliedTypeTree(tpt, args) =>
+ treeCopy.AppliedTypeTree(tree, transform(tpt), transformTrees(args))
+ case TypeBoundsTree(lo, hi) =>
+ treeCopy.TypeBoundsTree(tree, transform(lo), transform(hi))
+ case ExistentialTypeTree(tpt, whereClauses) =>
+ treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses))
+ case SelectFromArray(qualifier, selector, erasure) =>
+ treeCopy.SelectFromArray(tree, transform(qualifier), selector, erasure)
+ }
+
+ def transformTrees(trees: List[Tree]): List[Tree] =
+ trees mapConserve (transform(_))
+ def transformTemplate(tree: Template): Template =
+ transform(tree: Tree).asInstanceOf[Template]
+ def transformTypeDefs(trees: List[TypeDef]): List[TypeDef] =
+ trees mapConserve (tree => transform(tree).asInstanceOf[TypeDef])
+ def transformValDef(tree: ValDef): ValDef =
+ if (tree.isEmpty) tree else transform(tree).asInstanceOf[ValDef]
+ def transformValDefs(trees: List[ValDef]): List[ValDef] =
+ trees mapConserve (transformValDef(_))
+ def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] =
+ treess mapConserve (transformValDefs(_))
+ def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] =
+ trees mapConserve (tree => transform(tree).asInstanceOf[CaseDef])
+ def transformIdents(trees: List[Ident]): List[Ident] =
+ trees mapConserve (tree => transform(tree).asInstanceOf[Ident])
+ def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
+ stats mapConserve (stat =>
+ if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat))
+ else transform(stat)) filter (EmptyTree !=)
+ def transformModifiers(mods: Modifiers): Modifiers =
+ Modifiers(mods.flags, mods.privateWithin, transformTrees(mods.annotations), mods.positions)
+
+ def atOwner[A](owner: Symbol)(trans: => A): A = {
+ val prevOwner = currentOwner
+ currentOwner = owner
+ val result = trans
+ currentOwner = prevOwner
+ result
+ }
+ }
+
+ private[scala] def duplicateTree(tree: Tree): Tree = duplicator transform tree
+
+ private lazy val duplicator = new Transformer {
+ override val treeCopy = new StrictTreeCopier
+ override def transform(t: Tree) = {
+ val t1 = super.transform(t)
+ if ((t1 ne t) && isRangePos(t1.pos)) t1 setPos focusPos(t.pos)
+ t1
+ }
+ }
+
+ private class ShallowDuplicator(orig: Tree) extends Transformer {
+ override val treeCopy = new StrictTreeCopier
+ override def transform(tree: Tree) =
+ if (tree eq orig) super.transform(tree)
+ else tree
+ }
+
+ class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer {
+ override def transform(tree: Tree): Tree = tree match {
+ case Ident(_) =>
+ def subst(from: List[Symbol], to: List[Tree]): Tree =
+ if (from.isEmpty) tree
+ else if (tree.symbol == from.head) to.head
+ else subst(from.tail, to.tail);
+ subst(from, to)
+ case _ =>
+ super.transform(tree)
+ }
+ }
+
+ class TreeTypeSubstituter(val from: List[Symbol], val to: List[Type]) extends Traverser {
+ val typeSubst = new SubstTypeMap(from, to)
+ def fromContains = typeSubst.fromContains
+
+ override def traverse(tree: Tree) {
+ if (tree.tpe ne null) tree.tpe = typeSubst(tree.tpe)
+ if (tree.isDef) {
+ val sym = tree.symbol
+ val info1 = typeSubst(sym.info)
+ if (info1 ne sym.info) sym.setInfo(info1)
+ }
+ super.traverse(tree)
+ }
+ override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate)
+ override def toString() = "TreeTypeSubstituter("+from+","+to+")"
+ }
+
+ lazy val EmptyTreeTypeSubstituter = new TreeTypeSubstituter(List(), List())
+
+ class TreeSymSubstTraverser(val from: List[Symbol], val to: List[Symbol]) extends Traverser {
+ val subst = new SubstSymMap(from, to)
+ override def traverse(tree: Tree) {
+ if (tree.tpe ne null) tree.tpe = subst(tree.tpe)
+ if (tree.isDef) {
+ val sym = tree.symbol
+ val info1 = subst(sym.info)
+ if (info1 ne sym.info) sym.setInfo(info1)
+ }
+ super.traverse(tree)
+ }
+ override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate)
+ override def toString() = "TreeSymSubstTraverser("+from+","+to+")"
+ }
+
+ /** Substitute symbols in 'from' with symbols in 'to'. Returns a new
+ * tree using the new symbols and whose Ident and Select nodes are
+ * name-consistent with the new symbols.
+ */
+ class TreeSymSubstituter(from: List[Symbol], to: List[Symbol]) extends Transformer {
+ val symSubst = new SubstSymMap(from, to)
+ override def transform(tree: Tree): Tree = {
+ def subst(from: List[Symbol], to: List[Symbol]) {
+ if (!from.isEmpty)
+ if (tree.symbol == from.head) tree setSymbol to.head
+ else subst(from.tail, to.tail)
+ }
+
+ if (tree.tpe ne null) tree.tpe = symSubst(tree.tpe)
+ if (tree.hasSymbol) {
+ subst(from, to)
+ tree match {
+ case Ident(name0) if tree.symbol != NoSymbol =>
+ treeCopy.Ident(tree, tree.symbol.name)
+ case Select(qual, name0) =>
+ treeCopy.Select(tree, transform(qual), tree.symbol.name)
+ case _ =>
+ super.transform(tree)
+ }
+ } else
+ super.transform(tree)
+ }
+ def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T]
+ override def toString() = "TreeSymSubstituter("+from+","+to+")"
+ }
+
+ class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser {
+ def changeOwner(tree: Tree) = {
+ if ((tree.isDef || tree.isInstanceOf[Function]) &&
+ tree.symbol != NoSymbol && tree.symbol.owner == oldowner)
+ tree.symbol.owner = newowner
+ }
+ override def traverse(tree: Tree) {
+ changeOwner(tree)
+ super.traverse(tree)
+ }
+ }
+
+ object posAssigner extends Traverser {
+ var pos: Position = _
+ override def traverse(t: Tree) {
+ if (t != EmptyTree && t.pos == NoPosition) {
+ t.setPos(pos)
+ super.traverse(t)
+ }
+ }
+ }
+
+ def atPos[T <: Tree](pos: Position)(tree: T): T = {
+ posAssigner.pos = pos
+ posAssigner.traverse(tree)
+ tree
+ }
+
+ class ForeachPartialTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser {
+ override def traverse(tree: Tree) {
+ val t = if (pf isDefinedAt tree) pf(tree) else tree
+ super.traverse(t)
+ }
+ }
+
+ class ForeachTreeTraverser(f: Tree => Unit) extends Traverser {
+ override def traverse(t: Tree) {
+ f(t)
+ super.traverse(t)
+ }
+ }
+
+ class FilterTreeTraverser(p: Tree => Boolean) extends Traverser {
+ val hits = new ListBuffer[Tree]
+ override def traverse(t: Tree) {
+ if (p(t)) hits += t
+ super.traverse(t)
+ }
+ }
+
+ class FindTreeTraverser(p: Tree => Boolean) extends Traverser {
+ var result: Option[Tree] = None
+ override def traverse(t: Tree) {
+ if (result.isEmpty) {
+ if (p(t)) result = Some(t)
+ super.traverse(t)
+ }
+ }
+ }
+
+ object resetPos extends Traverser {
+ override def traverse(t: Tree) {
+ if (t != EmptyTree) t.setPos(NoPosition)
+ super.traverse(t)
+ }
+ }
+
+
+ /** resets symbol and tpe fields in a tree, @see ResetAttrsTraverse
+ */
+ def resetAllAttrs[A<:Tree](x:A): A = { new ResetAttrsTraverser().traverse(x); x }
+ def resetLocalAttrs[A<:Tree](x:A): A = { new ResetLocalAttrsTraverser().traverse(x); x }
+
+ /** A traverser which resets symbol and tpe fields of all nodes in a given tree
+ * except for (1) TypeTree nodes, whose <code>.tpe</code> field is kept, and
+ * (2) This(pkg) nodes, where pkg refers to a package symbol -- their attributes are kept, and
+ * (3) if a <code>.symbol</code> field refers to a symbol which is defined
+ * outside the tree, it is also kept.
+ *
+ * (2) is necessary because some This(pkg) are generated where pkg is not
+ * an enclosing package.n In that case, resetting the symbol would cause the
+ * next type checking run to fail. See #3152.
+ *
+ * (bq:) This traverser has mutable state and should be discarded after use
+ */
+ private class ResetAttrsTraverser extends Traverser {
+ protected def isLocal(sym: Symbol): Boolean = true
+ protected def resetDef(tree: Tree) {
+ tree.symbol = NoSymbol
+ }
+ override def traverse(tree: Tree): Unit = {
+ tree match {
+ case _: DefTree | Function(_, _) | Template(_, _, _) =>
+ resetDef(tree)
+ tree.tpe = null
+ case tpt: TypeTree =>
+ if (tpt.wasEmpty) tree.tpe = null
+ case This(_) if tree.symbol != null && tree.symbol.isPackageClass =>
+ ;
+ case EmptyTree =>
+ ;
+ case _ =>
+ if (tree.hasSymbol && isLocal(tree.symbol)) tree.symbol = NoSymbol
+ tree.tpe = null
+ }
+ super.traverse(tree)
+ }
+ }
+
+ private class ResetLocalAttrsTraverser extends ResetAttrsTraverser {
+ private val erasedSyms = HashSet[Symbol](8)
+ override protected def isLocal(sym: Symbol) = erasedSyms(sym)
+ override protected def resetDef(tree: Tree) {
+ erasedSyms addEntry tree.symbol
+ super.resetDef(tree)
+ }
+ override def traverse(tree: Tree): Unit = tree match {
+ case Template(parents, self, body) =>
+ for (stat <- body)
+ if (stat.isDef) erasedSyms.addEntry(stat.symbol)
+ super.traverse(tree)
+ case _ =>
+ super.traverse(tree)
+ }
+ }
+
+ /* A standard pattern match
+ case EmptyTree =>
+ case PackageDef(pid, stats) =>
+ // package pid { stats }
+ case ClassDef(mods, name, tparams, impl) =>
+ // mods class name [tparams] impl where impl = extends parents { defs }
+ case ModuleDef(mods, name, impl) => (eliminated by refcheck)
+ // mods object name impl where impl = extends parents { defs }
+ case ValDef(mods, name, tpt, rhs) =>
+ // mods val name: tpt = rhs
+ // note missing type information is expressed by tpt = TypeTree()
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ // mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs
+ // note missing type information is expressed by tpt = TypeTree()
+ case TypeDef(mods, name, tparams, rhs) => (eliminated by erasure)
+ // mods type name[tparams] = rhs
+ // mods type name[tparams] >: lo <: hi, where lo, hi are in a TypeBoundsTree,
+ and DEFERRED is set in mods
+ case LabelDef(name, params, rhs) =>
+ // used for tailcalls and like
+ // 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 ())
+ case Import(expr, selectors) => (eliminated by typecheck)
+ // import expr.{selectors}
+ // Selectors are a list of 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)))
+ case Template(parents, self, body) =>
+ // extends parents { self => body }
+ // if self is missing it is represented as emptyValDef
+ case Block(stats, expr) =>
+ // { stats; expr }
+ case CaseDef(pat, guard, body) => (eliminated by transmatch/explicitouter)
+ // case pat if guard => body
+ case Alternative(trees) => (eliminated by transmatch/explicitouter)
+ // pat1 | ... | patn
+ case Star(elem) => (eliminated by transmatch/explicitouter)
+ // pat*
+ case Bind(name, body) => (eliminated by transmatch/explicitouter)
+ // name @ pat
+ case UnApply(fun: Tree, args) (introduced by typer, eliminated by transmatch/explicitouter)
+ // used for unapply's
+ case ArrayValue(elemtpt, trees) => (introduced by uncurry)
+ // 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))))
+ case Function(vparams, body) => (eliminated by lambdaLift)
+ // vparams => body where vparams:List[ValDef]
+ case Assign(lhs, rhs) =>
+ // lhs = rhs
+ case If(cond, thenp, elsep) =>
+ // if (cond) thenp else elsep
+ case Match(selector, cases) =>
+ // selector match { cases }
+ case Return(expr) =>
+ // return expr
+ case Try(block, catches, finalizer) =>
+ // try block catch { catches } finally finalizer where catches: List[CaseDef]
+ case Throw(expr) =>
+ // throw expr
+ case New(tpt) =>
+ // new tpt always in the context: (new tpt).<init>[targs](args)
+ case Typed(expr, tpt) => (eliminated by erasure)
+ // expr: tpt
+ case TypeApply(fun, args) =>
+ // fun[args]
+ case Apply(fun, args) =>
+ // fun(args)
+ // for instance fun[targs](args) is expressed as Apply(TypeApply(fun, targs), args)
+ case ApplyDynamic(qual, args) (introduced by erasure, eliminated by cleanup)
+ // fun(args)
+ case Super(qual, mix) =>
+ // qual.super[mix] if qual and/or mix is empty, ther are tpnme.EMPTY
+ case This(qual) =>
+ // qual.this
+ case Select(qualifier, selector) =>
+ // qualifier.selector
+ case Ident(name) =>
+ // name
+ // note: type checker converts idents that refer to enclosing fields or methods
+ // to selects; name ==> this.name
+ case Literal(value) =>
+ // value
+ case TypeTree() => (introduced by refcheck)
+ // a type that's not written out, but given in the tpe attribute
+ case Annotated(annot, arg) => (eliminated by typer)
+ // arg @annot for types, arg: @annot for exprs
+ case SingletonTypeTree(ref) => (eliminated by uncurry)
+ // ref.type
+ case SelectFromTypeTree(qualifier, selector) => (eliminated by uncurry)
+ // qualifier # selector, a path-dependent type p.T is expressed as p.type # T
+ case CompoundTypeTree(templ: Template) => (eliminated by uncurry)
+ // parent1 with ... with parentN { refinement }
+ case AppliedTypeTree(tpt, args) => (eliminated by uncurry)
+ // tpt[args]
+ case TypeBoundsTree(lo, hi) => (eliminated by uncurry)
+ // >: lo <: hi
+ case ExistentialTypeTree(tpt, whereClauses) => (eliminated by uncurry)
+ // tpt forSome { whereClauses }
+
+*/
+}
+
diff --git a/src/compiler/scala/reflect/common/TypeDebugging.scala b/src/compiler/scala/reflect/common/TypeDebugging.scala
new file mode 100644
index 0000000000..6028473b39
--- /dev/null
+++ b/src/compiler/scala/reflect/common/TypeDebugging.scala
@@ -0,0 +1,72 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.reflect
+package common
+
+trait TypeDebugging {
+ self: SymbolTable =>
+
+ import definitions._
+
+ // @M toString that is safe during debugging (does not normalize, ...)
+ object TypeDebugStrings {
+ object str {
+ def parentheses(xs: List[_]): String = xs.mkString("(", ", ", ")")
+ def brackets(xs: List[_]): String = if (xs.isEmpty) "" else xs.mkString("[", ", ", "]")
+ def tparams(tparams: List[Type]): String = brackets(tparams map debug)
+ def parents(ps: List[Type]): String = (ps map debug).mkString(" with ")
+ def refine(defs: Scope): String = defs.toList.mkString("{", " ;\n ", "}")
+ }
+
+ def dump(tp: Type): Unit = {
+ println("** " + tp + " / " + tp.getClass + " **")
+ import tp._
+
+ println("typeSymbol = " + typeSymbol)
+ println("termSymbol = " + termSymbol)
+ println("widen = " + widen)
+ println("deconst = " + deconst)
+ println("typeOfThis = " + typeOfThis)
+ println("bounds = " + bounds)
+ println("parents = " + parents)
+ println("prefixChain = " + prefixChain)
+ println("typeConstructor = " + typeConstructor)
+ println(" .. typeConstructor.typeParams = " + typeConstructor.typeParams)
+ println(" .. _.variance = " + (typeConstructor.typeParams map (_.variance)))
+ println("typeArgs = " + typeArgs)
+ println("resultType = " + resultType)
+ println("finalResultType = " + finalResultType)
+ println("paramss = " + paramss)
+ println("paramTypes = " + paramTypes)
+ println("typeParams = " + typeParams)
+ println("boundSyms = " + boundSyms)
+ println("baseTypeSeq = " + baseTypeSeq)
+ println("baseClasses = " + baseClasses)
+ println("toLongString = " + toLongString)
+ }
+
+ private def debug(tp: Type): String = tp match {
+ case TypeRef(pre, sym, args) => debug(pre) + "." + sym.nameString + str.tparams(args)
+ case ThisType(sym) => sym.nameString + ".this"
+ case SingleType(pre, sym) => debug(pre) +"."+ sym.nameString +".type"
+ case RefinedType(parents, defs) => str.parents(parents) + str.refine(defs)
+ case ClassInfoType(parents, defs, clazz) => "class "+ clazz.nameString + str.parents(parents) + str.refine(defs)
+ case PolyType(tparams, result) => str.brackets(tparams) + " " + debug(result)
+ case TypeBounds(lo, hi) => ">: "+ debug(lo) +" <: "+ debug(hi)
+ case tv @ TypeVar(_, _) => tv.toString
+ case ExistentialType(tparams, qtpe) => "forSome "+ str.brackets(tparams) + " " + debug(qtpe)
+ case _ => tp.toString
+ }
+ def debugString(tp: Type) = debug(tp)
+ }
+ private def TDS = TypeDebugStrings
+
+ def paramString(tp: Type) = TDS.str parentheses (tp.params map (_.defString))
+ def typeParamsString(tp: Type) = TDS.str brackets (tp.typeParams map (_.defString))
+ def typeArgsString(tp: Type) = TDS.str brackets (tp.typeArgs map (_.safeToString))
+ def debugString(tp: Type) = TDS debugString tp
+}
+
diff --git a/src/compiler/scala/reflect/common/Types.scala b/src/compiler/scala/reflect/common/Types.scala
new file mode 100644
index 0000000000..78407cd868
--- /dev/null
+++ b/src/compiler/scala/reflect/common/Types.scala
@@ -0,0 +1,5699 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+
+import scala.collection.{ mutable, immutable }
+import scala.ref.WeakReference
+import mutable.ListBuffer
+//import ast.TreeGen
+//import util.{ Position, NoPosition }
+import Flags._
+import scala.util.control.ControlThrowable
+import scala.annotation.tailrec
+import util.Statistics._
+
+/* A standard type pattern match:
+ case ErrorType =>
+ // internal: error
+ case WildcardType =>
+ // internal: unknown
+ case NoType =>
+ case NoPrefix =>
+ case ThisType(sym) =>
+ // sym.this.type
+ case SuperType(thistpe, supertpe) =>
+ // super references
+ case SingleType(pre, sym) =>
+ // pre.sym.type
+ case ConstantType(value) =>
+ // Int(2)
+ case TypeRef(pre, sym, args) =>
+ // pre.sym[targs]
+ // Outer.this.C would be represented as TypeRef(ThisType(Outer), C, List())
+ case RefinedType(parents, defs) =>
+ // parent1 with ... with parentn { defs }
+ case ExistentialType(tparams, result) =>
+ // result forSome { tparams }
+ case AnnotatedType(annots, tp, selfsym) =>
+ // tp @annots
+
+ // the following are non-value types; you cannot write them down in Scala source.
+
+ case TypeBounds(lo, hi) =>
+ // >: lo <: hi
+ case ClassInfoType(parents, defs, clazz) =>
+ // same as RefinedType except as body of class
+ case MethodType(paramtypes, result) =>
+ // (paramtypes)result
+ // For instance def m(): T is represented as MethodType(List(), T)
+ case NullaryMethodType(result) => // eliminated by uncurry
+ // an eval-by-name type
+ // For instance def m: T is represented as NullaryMethodType(T)
+ case PolyType(tparams, result) =>
+ // [tparams]result where result is a (Nullary)MethodType or ClassInfoType
+
+ // The remaining types are not used after phase `typer'.
+ case OverloadedType(pre, tparams, alts) =>
+ // all alternatives of an overloaded ident
+ case AntiPolyType(pre, targs) =>
+ // rarely used, disappears when combined with a PolyType
+ case TypeVar(inst, constr) =>
+ // a type variable
+ // Replace occurrences of type parameters with type vars, where
+ // inst is the instantiation and constr is a list of bounds.
+ case DeBruijnIndex(level, index)
+ // for dependent method types: a type referring to a method parameter.
+ // Not presently used, it seems.
+*/
+
+trait Types /*extends reflect.generic.Types*/ { self: SymbolTable =>
+ import definitions._
+
+ //statistics
+ def uniqueTypeCount = if (uniques == null) 0 else uniques.size
+
+ private var explainSwitch = false
+ private final val emptySymbolSet = immutable.Set.empty[Symbol]
+
+ private final val alternativeNarrow = false
+
+ private final val LogPendingSubTypesThreshold = 50
+ private final val LogPendingBaseTypesThreshold = 50
+ private final val LogVolatileThreshold = 50
+
+ /** A don't care value for the depth parameter in lubs/glbs and related operations */
+ private final val AnyDepth = -3
+
+ /** Decrement depth unless it is a don't care */
+ private final def decr(depth: Int) = if (depth == AnyDepth) AnyDepth else depth - 1
+
+ private final val printLubs = false
+
+ /** The current skolemization level, needed for the algorithms
+ * in isSameType, isSubType that do constraint solving under a prefix
+ */
+ var skolemizationLevel = 0
+
+ /** A log of type variable with their original constraints. Used in order
+ * to undo constraints in the case of isSubType/isSameType failure.
+ */
+ object undoLog {
+ private type UndoLog = List[(TypeVar, TypeConstraint)]
+ private[scala] var log: UndoLog = List()
+
+ /** Undo all changes to constraints to type variables upto `limit'
+ */
+ private def undoTo(limit: UndoLog) {
+ while ((log ne limit) && log.nonEmpty) {
+ val (tv, constr) = log.head
+ tv.constr = constr
+ log = log.tail
+ }
+ }
+
+ private[Types] def record(tv: TypeVar) = {
+ log ::= (tv, tv.constr.cloneInternal)
+ }
+ private[scala] def clear() {
+ if (settings.debug.value)
+ self.log("Clearing " + log.size + " entries from the undoLog.")
+
+ log = Nil
+ }
+
+ // `block` should not affect constraints on typevars
+ def undo[T](block: => T): T = {
+ val before = log
+
+ try block
+ finally undoTo(before)
+ }
+
+ // if `block` evaluates to false, it should not affect constraints on typevars
+ def undoUnless(block: => Boolean): Boolean = {
+ val before = log
+ var result = false
+
+ try result = block
+ finally if (!result) undoTo(before)
+
+ result
+ }
+ }
+
+ /** A map from lists to compound types that have the given list as parents.
+ * This is used to avoid duplication in the computation of base type sequences and baseClasses.
+ * It makes use of the fact that these two operations depend only on the parents,
+ * not on the refinement.
+ */
+ val intersectionWitness = new mutable.WeakHashMap[List[Type], WeakReference[Type]]
+
+ //private object gen extends {
+ // val global : Types.this.type = Types.this
+ //} with TreeGen
+
+ //import gen._
+
+ /** A proxy for a type (identified by field `underlying') that forwards most
+ * operations to it (for exceptions, see WrappingProxy, which forwards even more operations).
+ * every operation that is overridden for some kind of types should be forwarded.
+ */
+ trait SimpleTypeProxy extends Type {
+ def underlying: Type
+
+ // the following operations + those in RewrappingTypeProxy are all operations
+ // in class Type that are overridden in some subclass
+ // Important to keep this up-to-date when new operations are added!
+ override def isTrivial = underlying.isTrivial
+ override def isHigherKinded: Boolean = underlying.isHigherKinded
+ override def typeConstructor: Type = underlying.typeConstructor
+ override def isNotNull = underlying.isNotNull
+ override def isError = underlying.isError
+ override def isErroneous = underlying.isErroneous
+ override def isStable: Boolean = underlying.isStable
+ override def isVolatile = underlying.isVolatile
+ override def finalResultType = underlying.finalResultType
+ override def paramSectionCount = underlying.paramSectionCount
+ override def paramss = underlying.paramss
+ override def params = underlying.params
+ override def paramTypes = underlying.paramTypes
+ override def termSymbol = underlying.termSymbol
+ override def termSymbolDirect = underlying.termSymbolDirect
+ override def typeParams = underlying.typeParams
+ override def boundSyms = underlying.boundSyms
+ override def typeSymbol = underlying.typeSymbol
+ override def typeSymbolDirect = underlying.typeSymbolDirect
+ override def widen = underlying.widen
+ override def typeOfThis = underlying.typeOfThis
+ override def bounds = underlying.bounds
+ override def parents = underlying.parents
+ override def prefix = underlying.prefix
+ override def decls = underlying.decls
+ override def baseType(clazz: Symbol) = underlying.baseType(clazz)
+ override def baseTypeSeq = underlying.baseTypeSeq
+ override def baseTypeSeqDepth = underlying.baseTypeSeqDepth
+ override def baseClasses = underlying.baseClasses
+ }
+
+ /** A proxy for a type (identified by field `underlying') that forwards most
+ * operations to it. Every operation that is overridden for some kind of types is
+ * forwarded here. Some operations are rewrapped again.
+ */
+ trait RewrappingTypeProxy extends SimpleTypeProxy {
+ protected def maybeRewrap(newtp: Type) = if (newtp eq underlying) this else rewrap(newtp)
+ protected def rewrap(newtp: Type): Type
+
+ // the following are all operations in class Type that are overridden in some subclass
+ // Important to keep this up-to-date when new operations are added!
+ override def widen = maybeRewrap(underlying.widen)
+ override def narrow = underlying.narrow
+ override def deconst = maybeRewrap(underlying.deconst)
+ override def resultType = maybeRewrap(underlying.resultType)
+ override def resultType(actuals: List[Type]) = maybeRewrap(underlying.resultType(actuals))
+ override def finalResultType = maybeRewrap(underlying.finalResultType)
+ override def paramSectionCount = 0
+ override def paramss: List[List[Symbol]] = List()
+ override def params: List[Symbol] = List()
+ override def paramTypes: List[Type] = List()
+ override def typeArgs = underlying.typeArgs
+ override def notNull = maybeRewrap(underlying.notNull)
+ override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = underlying.instantiateTypeParams(formals, actuals)
+ override def skolemizeExistential(owner: Symbol, origin: AnyRef) = underlying.skolemizeExistential(owner, origin)
+ override def normalize = maybeRewrap(underlying.normalize)
+ override def dealias = maybeRewrap(underlying.dealias)
+ override def cloneInfo(owner: Symbol) = maybeRewrap(underlying.cloneInfo(owner))
+ override def atOwner(owner: Symbol) = maybeRewrap(underlying.atOwner(owner))
+ override def prefixString = underlying.prefixString
+ override def isComplete = underlying.isComplete
+ override def complete(sym: Symbol) = underlying.complete(sym)
+ override def load(sym: Symbol) { underlying.load(sym) }
+ override def withAnnotations(annots: List[AnnotationInfo]) = maybeRewrap(underlying.withAnnotations(annots))
+ override def withoutAnnotations = maybeRewrap(underlying.withoutAnnotations)
+ }
+
+ /** The base class for all types */
+ abstract class Type {
+
+ /** Types for which asSeenFrom always is the identity, no matter what
+ * prefix or owner.
+ */
+ def isTrivial: Boolean = false
+
+ /** Is this type higher-kinded, i.e., is it a type constructor @M */
+ def isHigherKinded: Boolean = false
+
+ /** Does this type denote a stable reference (i.e. singleton type)? */
+ def isStable: Boolean = false
+
+ /** Is this type dangerous (i.e. it might contain conflicting
+ * type information when empty, so that it can be constructed
+ * so that type unsoundness results.) A dangerous type has an underlying
+ * type of the form T_1 with T_n { decls }, where one of the
+ * T_i (i > 1) is an abstract type.
+ */
+ def isVolatile: Boolean = false
+
+ /** Is this type guaranteed not to have `null' as a value? */
+ def isNotNull: Boolean = false
+
+ /** Is this type a structural refinement type (it 'refines' members that have not been inherited) */
+ def isStructuralRefinement: Boolean = false
+
+ /** Does this type depend immediately on an enclosing method parameter?
+ * i.e., is it a singleton type whose termSymbol refers to an argument of the symbol's owner (which is a method)
+ */
+ def isImmediatelyDependent: Boolean = false
+
+ /** Does this depend on an enclosing method parameter? */
+ def isDependent: Boolean = IsDependentCollector.collect(this)
+
+ /** True for WildcardType or BoundedWildcardType */
+ def isWildcard = false
+
+ /** Is this type produced as a repair for an error? */
+ def isError: Boolean = typeSymbol.isError || termSymbol.isError
+
+ /** Is this type produced as a repair for an error? */
+ def isErroneous: Boolean = ErroneousCollector.collect(this)
+
+ /** Does this type denote a reference type which can be null? */
+ // def isNullable: Boolean = false
+
+ /** Can this type only be subtyped by bottom types?
+ * This is assessed to be the case if the class is final,
+ * and all type parameters (if any) are invariant.
+ */
+ def isFinalType =
+ typeSymbol.isFinal && (typeSymbol.typeParams forall (_.variance == 0))
+
+ /** Is this type completed (i.e. not a lazy type)?
+ */
+ def isComplete: Boolean = true
+
+ /** If this is a lazy type, assign a new type to `sym'. */
+ def complete(sym: Symbol) {}
+
+ /** The term symbol associated with the type
+ * Note that the symbol of the normalized type is returned (@see normalize)
+ */
+ def termSymbol: Symbol = NoSymbol
+
+ /** The type symbol associated with the type
+ * Note that the symbol of the normalized type is returned (@see normalize)
+ */
+ def typeSymbol: Symbol = NoSymbol
+
+ /** The term symbol *directly* associated with the type
+ */
+ def termSymbolDirect: Symbol = termSymbol
+
+ /** The type symbol *directly* associated with the type
+ */
+ def typeSymbolDirect: Symbol = typeSymbol
+
+ /** The base type underlying a type proxy,
+ * identity on all other types */
+ def underlying: Type = this
+
+ /** Widen from singleton type to its underlying non-singleton
+ * base type by applying one or more `underlying' dereferences,
+ * identity for all other types.
+ *
+ * class Outer { class C ; val x: C }
+ * val o: Outer
+ * <o.x.type>.widen = o.C
+ */
+ def widen: Type = this
+
+ /** Map a constant type or not-null-type to its underlying base type,
+ * identity for all other types.
+ */
+ def deconst: Type = this
+
+ /** The type of `this' of a class type or reference type
+ */
+ def typeOfThis: Type = typeSymbol.typeOfThis
+
+ /** Map to a singleton type which is a subtype of this type.
+ * The fallback implemented here gives
+ * T.narrow = T' forSome { type T' <: T with Singleton }
+ * Overridden where we know more about where types come from.
+ */
+ def narrow: Type =
+ if (phase.erasedTypes) this
+ else commonOwner(this) freshExistential ".type" setInfo singletonBounds(this) tpe
+
+ /** For a TypeBounds type, itself;
+ * for a reference denoting an abstract type, its bounds,
+ * for all other types, a TypeBounds type all of whose bounds are this type.
+ */
+ def bounds: TypeBounds = TypeBounds(this, this)
+
+ /** For a class or intersection type, its parents.
+ * For a TypeBounds type, the parents of its hi bound.
+ * inherited by typerefs, singleton types, and refinement types,
+ * The empty list for all other types */
+ def parents: List[Type] = List()
+
+ /** For a typeref or single-type, the prefix of the normalized type (@see normalize).
+ * NoType for all other types. */
+ def prefix: Type = NoType
+
+ /** A chain of all typeref or singletype prefixes of this type, longest first.
+ * (Only used from safeToString.)
+ */
+ def prefixChain: List[Type] = this match {
+ case TypeRef(pre, _, _) => pre :: pre.prefixChain
+ case SingleType(pre, _) => pre :: pre.prefixChain
+ case _ => List()
+ }
+
+ /** This type, without its type arguments @M */
+ def typeConstructor: Type = this
+
+ /** For a typeref, its arguments. The empty list for all other types */
+ def typeArgs: List[Type] = List()
+
+ /** For a (nullary) method or poly type, its direct result type,
+ * the type itself for all other types. */
+ def resultType: Type = this
+
+ def resultType(actuals: List[Type]) = this
+
+ /** Only used for dependent method types. */
+ def resultApprox: Type = if (settings.YdepMethTpes.value) ApproximateDependentMap(resultType) else resultType
+
+ /** If this is a TypeRef `clazz`[`T`], return the argument `T`
+ * otherwise return this type
+ */
+ def remove(clazz: Symbol): Type = this
+
+ /** For a curried/nullary method or poly type its non-method result type,
+ * the type itself for all other types */
+ def finalResultType: Type = this
+
+ /** For a method type, the number of its value parameter sections,
+ * 0 for all other types */
+ def paramSectionCount: Int = 0
+
+ /** For a method or poly type, a list of its value parameter sections,
+ * the empty list for all other types */
+ def paramss: List[List[Symbol]] = List()
+
+ /** For a method or poly type, its first value parameter section,
+ * the empty list for all other types */
+ def params: List[Symbol] = List()
+
+ /** For a method or poly type, the types of its first value parameter section,
+ * the empty list for all other types */
+ def paramTypes: List[Type] = List()
+
+ /** For a (potentially wrapped) poly type, its type parameters,
+ * the empty list for all other types */
+ def typeParams: List[Symbol] = List()
+
+ /** For a (potentially wrapped) poly or existential type, its bound symbols,
+ * the empty list for all other types */
+ def boundSyms: immutable.Set[Symbol] = emptySymbolSet
+
+ /** Mixin a NotNull trait unless type already has one
+ * ...if the option is given, since it is causing typing bugs.
+ */
+ def notNull: Type =
+ if (!settings.Ynotnull.value || isNotNull || phase.erasedTypes) this
+ else NotNullType(this)
+
+ /** Replace formal type parameter symbols with actual type arguments.
+ *
+ * Amounts to substitution except for higher-kinded types. (See overridden method in TypeRef) -- @M
+ */
+ def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type =
+ if (sameLength(formals, actuals)) this.subst(formals, actuals) else ErrorType
+
+ /** If this type is an existential, turn all existentially bound variables to type skolems.
+ * @param owner The owner of the created type skolems
+ * @param origin The tree whose type was an existential for which the skolem was created.
+ */
+ def skolemizeExistential(owner: Symbol, origin: AnyRef): Type = this
+
+ /** A simple version of skolemizeExistential for situations where
+ * owner or unpack location do not matter (typically used in subtype tests)
+ */
+ def skolemizeExistential: Type = skolemizeExistential(NoSymbol, null)
+
+ /** Reduce to beta eta-long normal form.
+ * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes.
+ * Functions on types are also implemented as PolyTypes.
+ *
+ * Example: (in the below, <List> is the type constructor of List)
+ * TypeRef(pre, <List>, List()) is replaced by
+ * PolyType(X, TypeRef(pre, <List>, List(X)))
+ */
+ def normalize = this // @MAT
+
+ /** Expands type aliases. */
+ def dealias = this
+
+
+ /** For a classtype or refined type, its defined or declared members;
+ * inherited by subtypes and typerefs.
+ * The empty scope for all other types.
+ */
+ def decls: Scope = EmptyScope
+
+ /** The defined or declared members with name `name' in this type;
+ * an OverloadedSymbol if several exist, NoSymbol if none exist.
+ * Alternatives of overloaded symbol appear in the order they are declared.
+ */
+ def decl(name: Name): Symbol = findDecl(name, 0)
+
+ /** The non-private defined or declared members with name `name' in this type;
+ * an OverloadedSymbol if several exist, NoSymbol if none exist.
+ * Alternatives of overloaded symbol appear in the order they are declared.
+ */
+ def nonPrivateDecl(name: Name): Symbol = findDecl(name, PRIVATE)
+
+ /** A list of all members of this type (defined or inherited)
+ * Members appear in linearization order of their owners.
+ * Members with the same owner appear in reverse order of their declarations.
+ */
+ def members: List[Symbol] = findMember(nme.ANYNAME, 0, 0, false).alternatives
+
+ /** A list of all non-private members of this type (defined or inherited) */
+ def nonPrivateMembers: List[Symbol] =
+ findMember(nme.ANYNAME, PRIVATE | BRIDGES, 0, false).alternatives
+
+ /** A list of all non-private members of this type (defined or inherited),
+ * admitting members with given flags `admit`
+ */
+ def nonPrivateMembersAdmitting(admit: Long): List[Symbol] =
+ findMember(nme.ANYNAME, (PRIVATE | BRIDGES) & ~admit, 0, false).alternatives
+
+ /** A list of all implicit symbols of this type (defined or inherited) */
+ def implicitMembers: List[Symbol] =
+ findMember(nme.ANYNAME, BRIDGES, IMPLICIT, false).alternatives
+
+ /** A list of all deferred symbols of this type (defined or inherited) */
+ def deferredMembers: List[Symbol] =
+ findMember(nme.ANYNAME, BRIDGES, DEFERRED, false).alternatives
+
+ /** The member with given name,
+ * an OverloadedSymbol if several exist, NoSymbol if none exist */
+ def member(name: Name): Symbol = findMember(name, BRIDGES, 0, false)
+
+ /** The non-private member with given name,
+ * an OverloadedSymbol if several exist, NoSymbol if none exist.
+ * Bridges are excluded from the result
+ */
+ def nonPrivateMember(name: Name): Symbol =
+ findMember(name, PRIVATE | BRIDGES, 0, false)
+
+ /** The non-private member with given name, admitting members with given flags `admit`
+ * an OverloadedSymbol if several exist, NoSymbol if none exist
+ */
+ def nonPrivateMemberAdmitting(name: Name, admit: Long): Symbol =
+ findMember(name, (PRIVATE | BRIDGES) & ~admit, 0, false)
+
+ /** The non-local member with given name,
+ * an OverloadedSymbol if several exist, NoSymbol if none exist */
+ def nonLocalMember(name: Name): Symbol =
+ findMember(name, LOCAL | BRIDGES, 0, false)
+
+ /** The least type instance of given class which is a supertype
+ * of this type. Example:
+ * class D[T]
+ * class C extends p.D[Int]
+ * ThisType(C).baseType(D) = p.D[Int]
+ */
+ def baseType(clazz: Symbol): Type = NoType
+
+ /** This type as seen from prefix `pre' and class `clazz'. This means:
+ * Replace all thistypes of `clazz' or one of its subclasses
+ * by `pre' and instantiate all parameters by arguments of `pre'.
+ * Proceed analogously for thistypes referring to outer classes.
+ *
+ * Example:
+ * class D[T] { def m: T }
+ * class C extends p.D[Int]
+ * T.asSeenFrom(ThisType(C), D) (where D is owner of m)
+ * = Int
+ */
+ def asSeenFrom(pre: Type, clazz: Symbol): Type =
+ if (!isTrivial && (!phase.erasedTypes || pre.typeSymbol == ArrayClass)) {
+ incCounter(asSeenFromCount)
+ val start = startTimer(asSeenFromNanos)
+ val m = new AsSeenFromMap(pre.normalize, clazz)
+ val tp = m apply this
+ val result = existentialAbstraction(m.capturedParams, tp)
+ stopTimer(asSeenFromNanos, start)
+ result
+ } else this
+
+ /** The info of `sym', seen as a member of this type.
+ *
+ * Example:
+ * class D[T] { def m: T }
+ * class C extends p.D[Int]
+ * ThisType(C).memberType(m) = Int
+ */
+ def memberInfo(sym: Symbol): Type = {
+ sym.info.asSeenFrom(this, sym.owner)
+ }
+
+ /** The type of `sym', seen as a member of this type. */
+ def memberType(sym: Symbol): Type = sym match {
+ case meth: MethodSymbol =>
+ meth.typeAsMemberOf(this)
+ case _ =>
+ computeMemberType(sym)
+ }
+
+ def computeMemberType(sym: Symbol): Type = sym.tpeHK match { //@M don't prematurely instantiate higher-kinded types, they will be instantiated by transform, typedTypeApply, etc. when really necessary
+ case OverloadedType(_, alts) =>
+ OverloadedType(this, alts)
+ case tp =>
+ tp.asSeenFrom(this, sym.owner)
+ }
+
+ /** Substitute types `to' for occurrences of references to
+ * symbols `from' in this type.
+ */
+ def subst(from: List[Symbol], to: List[Type]): Type =
+ new SubstTypeMap(from, to) apply this
+
+ /** Substitute symbols `to' for occurrences of symbols
+ * `from' in this type.
+ * !!! NOTE !!!: If you need to do a substThis and a substSym, the substThis has to come
+ * first, as otherwise symbols will immediately get rebound in typeRef to the old
+ * symbol.
+ */
+ def substSym(from: List[Symbol], to: List[Symbol]): Type =
+ if (from eq to) this
+ else new SubstSymMap(from, to) apply this
+
+ /** Substitute all occurrences of `ThisType(from)' in this type
+ * by `to'.
+ * !!! NOTE !!!: If you need to do a substThis and a substSym, the substThis has to come
+ * first, as otherwise symbols will immediately get rebound in typeRef to the old
+ * symbol.
+ */
+ def substThis(from: Symbol, to: Type): Type =
+ new SubstThisMap(from, to) apply this
+
+ def substSuper(from: Type, to: Type): Type =
+ new SubstSuperMap(from, to) apply this
+
+ /** Returns all parts of this type which satisfy predicate `p' */
+ def filter(p: Type => Boolean): List[Type] = new FilterTypeCollector(p).collect(this).toList
+
+ /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p',
+ * or None if none exists.
+ */
+ def find(p: Type => Boolean): Option[Type] = new FindTypeCollector(p).collect(this)
+
+ /** Apply `f' to each part of this type */
+ def foreach(f: Type => Unit) { new ForEachTypeTraverser(f).traverse(this) }
+
+ /** Apply `f' to each part of this type; children get mapped before their parents */
+ def map(f: Type => Type): Type = new TypeMap {
+ def apply(x: Type) = f(mapOver(x))
+ } apply this
+
+ /** Is there part of this type which satisfies predicate `p'? */
+ def exists(p: Type => Boolean): Boolean = !find(p).isEmpty
+
+ /** Does this type contain a reference to this symbol? */
+ def contains(sym: Symbol): Boolean = new ContainsCollector(sym).collect(this)
+
+ /** Does this type contain a reference to this type */
+ def containsTp(tp: Type): Boolean = new ContainsTypeCollector(tp).collect(this)
+
+ /** Is this type a subtype of that type? */
+ def <:<(that: Type): Boolean = {
+ if (util.Statistics.enabled) stat_<:<(that)
+ else {
+ (this eq that) ||
+ (if (explainSwitch) explain("<:", isSubType, this, that)
+ else isSubType(this, that, AnyDepth))
+ }
+ }
+
+
+
+ /** Is this type a subtype of that type in a pattern context?
+ * Any type arguments on the right hand side are replaced with
+ * fresh existentials, except for Arrays.
+ *
+ * See bug1434.scala for an example of code which would fail
+ * if only a <:< test were applied.
+ */
+ def matchesPattern(that: Type): Boolean = {
+ (this <:< that) || ((this, that) match {
+ case (TypeRef(_, ArrayClass, List(arg1)), TypeRef(_, ArrayClass, List(arg2))) if arg2.typeSymbol.typeParams.nonEmpty =>
+ arg1 matchesPattern arg2
+ case (_, TypeRef(_, _, args)) =>
+ val newtp = existentialAbstraction(args map (_.typeSymbol), that)
+ !(that =:= newtp) && (this <:< newtp)
+ case _ =>
+ false
+ })
+ }
+
+ def stat_<:<(that: Type): Boolean = {
+ incCounter(subtypeCount)
+ val start = startTimer(subtypeNanos)
+ val result =
+ (this eq that) ||
+ (if (explainSwitch) explain("<:", isSubType, this, that)
+ else isSubType(this, that, AnyDepth))
+ stopTimer(subtypeNanos, start)
+ result
+ }
+
+ /** Is this type a weak subtype of that type? True also for numeric types, i.e. Int weak_<:< Long.
+ */
+ def weak_<:<(that: Type): Boolean = {
+ incCounter(subtypeCount)
+ val start = startTimer(subtypeNanos)
+ val result =
+ ((this eq that) ||
+ (if (explainSwitch) explain("weak_<:", isWeakSubType, this, that)
+ else isWeakSubType(this, that)))
+ stopTimer(subtypeNanos, start)
+ result
+ }
+
+ /** Is this type equivalent to that type? */
+ def =:=(that: Type): Boolean = (
+ (this eq that) ||
+ (if (explainSwitch) explain("=", isSameType, this, that)
+ else isSameType(this, that))
+ );
+
+ /** Does this type implement symbol `sym' with same or stronger type?
+ */
+ def specializes(sym: Symbol): Boolean =
+ if (explainSwitch) explain("specializes", specializesSym, this, sym)
+ else specializesSym(this, sym)
+
+ /** Is this type close enough to that type so that members
+ * with the two type would override each other?
+ * This means:
+ * - Either both types are polytypes with the same number of
+ * type parameters and their result types match after renaming
+ * corresponding type parameters
+ * - Or both types are (nullary) method types with equivalent type parameter types
+ * and matching result types
+ * - Or both types are equivalent
+ * - Or phase.erasedTypes is false and both types are neither method nor
+ * poly types.
+ */
+ def matches(that: Type): Boolean = matchesType(this, that, !phase.erasedTypes)
+
+ /** Same as matches, except that non-method types are always assumed to match.
+ */
+ def looselyMatches(that: Type): Boolean = matchesType(this, that, true)
+
+ /** The shortest sorted upwards closed array of types that contains
+ * this type as first element.
+ *
+ * A list or array of types ts is upwards closed if
+ *
+ * for all t in ts:
+ * for all typerefs p.s[args] such that t <: p.s[args]
+ * there exists a typeref p'.s[args'] in ts such that
+ * t <: p'.s['args] <: p.s[args],
+ *
+ * and
+ *
+ * for all singleton types p.s such that t <: p.s
+ * there exists a singleton type p'.s in ts such that
+ * t <: p'.s <: p.s
+ *
+ * Sorting is with respect to Symbol.isLess() on type symbols.
+ */
+ def baseTypeSeq: BaseTypeSeq = baseTypeSingletonSeq(this)
+
+ /** The maximum depth (@see maxDepth)
+ * of each type in the BaseTypeSeq of this type.
+ */
+ def baseTypeSeqDepth: Int = 1
+
+ /** The list of all baseclasses of this type (including its own typeSymbol)
+ * in reverse linearization order, starting with the class itself and ending
+ * in class Any.
+ */
+ def baseClasses: List[Symbol] = List()
+
+ /**
+ * @param sym the class symbol
+ * @return the index of given class symbol in the BaseTypeSeq of this type,
+ * or -1 if no base type with given class symbol exists.
+ */
+ def baseTypeIndex(sym: Symbol): Int = {
+ val bts = baseTypeSeq
+ var lo = 0
+ var hi = bts.length - 1
+ while (lo <= hi) {
+ val mid = (lo + hi) / 2
+ val btssym = bts.typeSymbol(mid)
+ if (sym == btssym) return mid
+ else if (sym isLess btssym) hi = mid - 1
+ else if (btssym isLess sym) lo = mid + 1
+ else abort()
+ }
+ -1
+ }
+
+ /** If this is a poly- or methodtype, a copy with cloned type / value parameters
+ * owned by `owner'. Identity for all other types.
+ */
+ def cloneInfo(owner: Symbol) = this
+
+ /** Make sure this type is correct as the info of given owner; clone it if not.
+ */
+ def atOwner(owner: Symbol) = this
+
+ protected def objectPrefix = "object "
+ protected def packagePrefix = "package "
+
+ def trimPrefix(str: String) = str stripPrefix objectPrefix stripPrefix packagePrefix
+
+ /** The string representation of this type used as a prefix */
+ def prefixString = trimPrefix(toString) + "#"
+
+ /** Convert toString avoiding infinite recursions by cutting off
+ * after `maxTostringRecursions` recursion levels. Uses `safeToString`
+ * to produce a string on each level.
+ */
+ override def toString: String =
+ if (tostringRecursions >= maxTostringRecursions)
+ "..."
+ else
+ try {
+ tostringRecursions += 1
+ safeToString
+ } finally {
+ tostringRecursions -= 1
+ }
+
+ /** Method to be implemented in subclasses.
+ * Converts this type to a string in calling toString for its parts.
+ */
+ def safeToString: String = super.toString
+
+ /** The string representation of this type, with singletypes explained */
+ def toLongString = {
+ val str = toString
+ if (str endsWith ".type") str + " (with underlying type " + widen + ")"
+ else str
+ }
+
+ /** A test whether a type contains any unification type variables */
+ def isGround: Boolean = this match {
+ case TypeVar(_, constr) =>
+ constr.instValid && constr.inst.isGround
+ case TypeRef(pre, sym, args) =>
+ sym.isPackageClass || pre.isGround && (args forall (_.isGround))
+ case SingleType(pre, sym) =>
+ sym.isPackageClass || pre.isGround
+ case ThisType(_) | NoPrefix | WildcardType | NoType | ErrorType | ConstantType(_) =>
+ true
+ case _ =>
+ typeVarToOriginMap(this) eq this
+ }
+
+ /** If this is a symbol loader type, load and assign a new type to
+ * `sym'.
+ */
+ def load(sym: Symbol) {}
+
+ private def findDecl(name: Name, excludedFlags: Int): Symbol = {
+ var alts: List[Symbol] = List()
+ var sym: Symbol = NoSymbol
+ var e: ScopeEntry = decls.lookupEntry(name)
+ while (e ne null) {
+ if (!e.sym.hasFlag(excludedFlags)) {
+ if (sym == NoSymbol) sym = e.sym
+ else {
+ if (alts.isEmpty) alts = List(sym)
+ alts = e.sym :: alts
+ }
+ }
+ e = decls.lookupNextEntry(e)
+ }
+ if (alts.isEmpty) sym
+ else (baseClasses.head.newOverloaded(this, alts))
+ }
+
+ /**
+ * Find member(s) in this type. If several members matching criteria are found, they are
+ * returned in an OverloadedSymbol
+ *
+ * @param name The member's name, where nme.ANYNAME means `unspecified'
+ * @param excludedFlags Returned members do not have these flags
+ * @param requiredFlags Returned members do have these flags
+ * @param stableOnly If set, return only members that are types or stable values
+ */
+ //TODO: use narrow only for modules? (correct? efficiency gain?)
+ def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = {
+ val suspension = TypeVar.Suspension
+ // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
+ // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
+ // without this, the matchesType call would lead to type variables on both sides
+ // of a subtyping/equality judgement, which can lead to recursive types being constructed.
+ // See (t0851) for a situation where this happens.
+ if (!this.isGround) {
+ // PP: The foreach below was formerly expressed as:
+ // for(tv @ TypeVar(_, _) <- this) { suspension suspend tv }
+ //
+ // The tree checker failed this saying a TypeVar is required, but a (Type @unchecked) was found.
+ // This is a consequence of using a pattern match and variable binding + ticket #1503, which
+ // was addressed by weakening the type of bindings in pattern matches if they occur on the right.
+ // So I'm not quite sure why this works at all, as the checker is right that it is mistyped.
+ // For now I modified it as below, which achieves the same without error.
+ //
+ // make each type var in this type use its original type for comparisons instead of collecting constraints
+ this foreach {
+ case tv: TypeVar => suspension suspend tv
+ case _ => ()
+ }
+ }
+
+ incCounter(findMemberCount)
+ val start = startTimer(findMemberNanos)
+
+ //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
+ var members: Scope = null
+ var member: Symbol = NoSymbol
+ var excluded = excludedFlags | DEFERRED
+ var continue = true
+ var self: Type = null
+ var membertpe: Type = null
+ while (continue) {
+ continue = false
+ val bcs0 = baseClasses
+ var bcs = bcs0
+ while (!bcs.isEmpty) {
+ val decls = bcs.head.info.decls
+ var entry =
+ if (name == nme.ANYNAME) decls.elems else decls.lookupEntry(name)
+ while (entry ne null) {
+ val sym = entry.sym
+ if (sym hasAllFlags requiredFlags) {
+ val excl = sym.getFlag(excluded)
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ !sym.isPrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (name.isTypeName || stableOnly && sym.isStable) {
+ stopTimer(findMemberNanos, start)
+ suspension.resumeAll
+ return sym
+ } else if (member == NoSymbol) {
+ member = sym
+ } else if (members eq null) {
+ if (member.name != sym.name ||
+ !(member == sym ||
+ member.owner != sym.owner &&
+ !sym.isPrivate && {
+ if (self eq null) self = this.narrow
+ if (membertpe eq null) membertpe = self.memberType(member)
+ (membertpe matches self.memberType(sym))
+ })) {
+ members = new Scope(List(member, sym))
+ }
+ } else {
+ var prevEntry = members.lookupEntry(sym.name)
+ while ((prevEntry ne null) &&
+ !(prevEntry.sym == sym ||
+ prevEntry.sym.owner != sym.owner &&
+ !sym.hasFlag(PRIVATE) && {
+ if (self eq null) self = this.narrow
+ self.memberType(prevEntry.sym) matches self.memberType(sym)
+ })) {
+ prevEntry = members lookupNextEntry prevEntry
+ }
+ if (prevEntry eq null) {
+ members enter sym
+ }
+ }
+ } else if (excl == DEFERRED.toLong) {
+ continue = true
+ }
+ }
+ entry = if (name == nme.ANYNAME) entry.next else decls lookupNextEntry entry
+ } // while (entry ne null)
+ // excluded = excluded | LOCAL
+ bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
+ } // while (!bcs.isEmpty)
+ excluded = excludedFlags
+ } // while (continue)
+ stopTimer(findMemberNanos, start)
+ suspension.resumeAll
+ if (members eq null) {
+ if (member == NoSymbol) incCounter(noMemberCount)
+ member
+ } else {
+ incCounter(multMemberCount)
+ baseClasses.head.newOverloaded(this, members.toList)
+ }
+ }
+
+ /** The existential skolems and existentially quantified variables which are free in this type */
+ def existentialSkolems: List[Symbol] = {
+ var boundSyms: List[Symbol] = List()
+ var skolems: List[Symbol] = List()
+ for (t <- this) {
+ t match {
+ case ExistentialType(quantified, qtpe) =>
+ boundSyms = boundSyms ::: quantified
+ case TypeRef(_, sym, _) =>
+ if ((sym hasFlag EXISTENTIAL) && !(boundSyms contains sym) && !(skolems contains sym))
+ skolems = sym :: skolems
+ case _ =>
+ }
+ }
+ skolems
+ }
+
+ /** Return the annotations on this type. */
+ def annotations: List[AnnotationInfo] = Nil
+
+ /** Test for the presence of an annotation */
+ def hasAnnotation(clazz: Symbol) = annotations exists { _.atp.typeSymbol == clazz }
+
+ /** Add an annotation to this type */
+ def withAnnotation(annot: AnnotationInfo) = withAnnotations(List(annot))
+
+ /** Add a number of annotations to this type */
+ def withAnnotations(annots: List[AnnotationInfo]): Type =
+ annots match {
+ case Nil => this
+ case _ => AnnotatedType(annots, this, NoSymbol)
+ }
+
+ /** Remove any annotations from this type */
+ def withoutAnnotations = this
+
+ /** Remove any annotations from this type and from any
+ * types embedded in this type. */
+ def stripAnnotations = StripAnnotationsMap(this)
+
+ /** Set the self symbol of an annotated type, or do nothing
+ * otherwise. */
+ def withSelfsym(sym: Symbol) = this
+
+ /** The selfsym of an annotated type, or NoSymbol of anything else */
+ def selfsym: Symbol = NoSymbol
+
+ /** The kind of this type; used for debugging */
+ def kind: String = "unknown type of class "+getClass()
+ }
+
+// Subclasses ------------------------------------------------------------
+
+ trait UniqueType {
+ override lazy val hashCode: Int = super.hashCode()
+ }
+
+ /** A base class for types that defer some operations
+ * to their immediate supertype.
+ */
+ abstract class SubType extends Type {
+ def supertype: Type
+ override def parents: List[Type] = supertype.parents
+ override def decls: Scope = supertype.decls
+ override def baseType(clazz: Symbol): Type = supertype.baseType(clazz)
+ override def baseTypeSeq: BaseTypeSeq = supertype.baseTypeSeq
+ override def baseTypeSeqDepth: Int = supertype.baseTypeSeqDepth
+ override def baseClasses: List[Symbol] = supertype.baseClasses
+ override def isNotNull = supertype.isNotNull
+ }
+
+ case class NotNullType(override val underlying: Type) extends SubType with RewrappingTypeProxy {
+ def supertype = underlying
+ protected def rewrap(newtp: Type): Type = NotNullType(newtp)
+ override def isNotNull: Boolean = true
+ override def notNull = this
+ override def deconst: Type = underlying //todo: needed?
+ override def safeToString: String = underlying.toString + " with NotNull"
+ override def kind = "NotNullType"
+ }
+
+ /** A base class for types that represent a single value
+ * (single-types and this-types).
+ */
+ abstract class SingletonType extends SubType with SimpleTypeProxy {
+ def supertype = underlying
+ override def isTrivial = false
+ override def isStable = true
+ override def isVolatile = underlying.isVolatile
+ override def widen: Type = underlying.widen
+ override def baseTypeSeq: BaseTypeSeq = {
+ incCounter(singletonBaseTypeSeqCount)
+ underlying.baseTypeSeq prepend this
+ }
+ override def isHigherKinded = false // singleton type classifies objects, thus must be kind *
+ override def safeToString: String = prefixString + "type"
+/*
+ override def typeOfThis: Type = typeSymbol.typeOfThis
+ override def bounds: TypeBounds = TypeBounds(this, this)
+ override def prefix: Type = NoType
+ override def typeArgs: List[Type] = List()
+ override def typeParams: List[Symbol] = List()
+*/
+ }
+
+ /** An object representing an erroneous type */
+ case object ErrorType extends Type {
+ // todo see whether we can do without
+ override def isError: Boolean = true
+ override def decls: Scope = new ErrorScope(NoSymbol)
+ override def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = {
+ var sym = decls lookup name
+ if (sym == NoSymbol) {
+ sym = NoSymbol.newErrorSymbol(name)
+ decls enter sym
+ }
+ sym
+ }
+ override def baseType(clazz: Symbol): Type = this
+ override def safeToString: String = "<error>"
+ override def narrow: Type = this
+ // override def isNullable: Boolean = true
+ override def kind = "ErrorType"
+ }
+
+ /** An object representing an unknown type, used during type inference.
+ * If you see WildcardType outside of inference it is almost certainly a bug.
+ */
+ case object WildcardType extends Type {
+ override def isWildcard = true
+ override def safeToString: String = "?"
+ // override def isNullable: Boolean = true
+ override def kind = "WildcardType"
+ }
+
+ case class BoundedWildcardType(override val bounds: TypeBounds) extends Type {
+ override def isWildcard = true
+ override def safeToString: String = "?" + bounds
+ override def kind = "BoundedWildcardType"
+ }
+
+ /** An object representing a non-existing type */
+ case object NoType extends Type {
+ override def isTrivial: Boolean = true
+ override def safeToString: String = "<notype>"
+ // override def isNullable: Boolean = true
+ override def kind = "NoType"
+ }
+
+ /** An object representing a non-existing prefix */
+ case object NoPrefix extends Type {
+ override def isTrivial: Boolean = true
+ override def isStable: Boolean = true
+ override def prefixString = ""
+ override def safeToString: String = "<noprefix>"
+ // override def isNullable: Boolean = true
+ override def kind = "NoPrefixType"
+ }
+
+ /** A class for this-types of the form <sym>.this.type
+ */
+ abstract case class ThisType(sym: Symbol) extends SingletonType {
+ //assert(sym.isClass && !sym.isModuleClass || sym.isRoot, sym)
+ override def isTrivial: Boolean = sym.isPackageClass
+ override def isNotNull = true
+ override def typeSymbol = sym
+ override def underlying: Type = sym.typeOfThis
+ override def isVolatile = false
+ override def isHigherKinded = sym.isRefinementClass && underlying.isHigherKinded
+ override def prefixString =
+ if (settings.debug.value) sym.nameString + ".this."
+ else if (sym.isAnonOrRefinementClass) "this."
+ else if (sym.printWithoutPrefix) ""
+ else if (sym.isModuleClass) sym.fullName + "."
+ else sym.nameString + ".this."
+ override def safeToString: String =
+ if (sym.isRoot) "<root>"
+ else if (sym.isEmptyPackageClass) "<empty>"
+ else super.safeToString
+ override def narrow: Type = this
+ override def kind = "ThisType"
+ }
+
+ object ThisType {
+ def apply(sym: Symbol): Type =
+ if (!phase.erasedTypes) unique(new ThisType(sym) with UniqueType)
+ else if (sym.isImplClass) sym.typeOfThis
+ else sym.tpe
+ }
+
+ /** A class for singleton types of the form <prefix>.<sym.name>.type.
+ * Cannot be created directly; one should always use
+ * `singleType' for creation.
+ */
+ case class SingleType(pre: Type, sym: Symbol) extends SingletonType {
+ override val isTrivial: Boolean = pre.isTrivial
+ // override def isNullable = underlying.isNullable
+ override def isNotNull = underlying.isNotNull
+ private var underlyingCache: Type = NoType
+ private var underlyingPeriod = NoPeriod
+ override def underlying: Type = {
+ val period = underlyingPeriod
+ if (period != currentPeriod) {
+ underlyingPeriod = currentPeriod
+ if (!isValid(period)) {
+ underlyingCache = pre.memberType(sym).resultType;
+ assert(underlyingCache ne this, this)
+ }
+ }
+ underlyingCache
+ }
+
+ // more precise conceptually, but causes cyclic errors: (paramss exists (_ contains sym))
+ override def isImmediatelyDependent = (sym ne NoSymbol) && (sym.owner.isMethod && sym.isValueParameter)
+
+ override def isVolatile : Boolean = underlying.isVolatile && !sym.isStable
+/*
+ override def narrow: Type = {
+ if (phase.erasedTypes) this
+ else {
+ val thissym = refinedType(List(this), sym.owner, EmptyScope).typeSymbol
+ if (sym.owner != NoSymbol) {
+ //Console.println("narrowing module " + sym + thissym.owner);
+ thissym.typeOfThis = this
+ }
+ thissym.thisType
+ }
+ }
+*/
+ override def narrow: Type = this
+
+ override def termSymbol = sym
+ override def prefix: Type = pre
+ override def prefixString: String =
+ if ((sym.isEmptyPackage || sym.isInterpreterWrapper || sym.isPredefModule || sym.isScalaPackage) && !settings.debug.value) ""
+ else pre.prefixString + sym.nameString + "."
+ override def kind = "SingleType"
+ }
+
+ abstract case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType {
+ override val isTrivial: Boolean = thistpe.isTrivial && supertpe.isTrivial
+ override def isNotNull = true;
+ override def typeSymbol = thistpe.typeSymbol
+ override def underlying = supertpe
+ override def prefix: Type = supertpe.prefix
+ override def prefixString = thistpe.prefixString.replaceAll("""this\.$""", "super.")
+ override def narrow: Type = thistpe.narrow
+ override def kind = "SuperType"
+ }
+
+ object SuperType {
+ def apply(thistp: Type, supertp: Type): Type =
+ if (phase.erasedTypes) supertp
+ else unique(new SuperType(thistp, supertp) with UniqueType)
+ }
+
+ /** A class for the bounds of abstract types and type parameters
+ */
+ abstract case class TypeBounds(lo: Type, hi: Type) extends SubType {
+ def supertype = hi
+ override val isTrivial: Boolean = lo.isTrivial && hi.isTrivial
+ override def bounds: TypeBounds = this
+ def containsType(that: Type) = that match {
+ case TypeBounds(_, _) => that <:< this
+ case _ => lo <:< that && that <:< hi
+ }
+ // override def isNullable: Boolean = NullClass.tpe <:< lo;
+ override def safeToString = ">: " + lo + " <: " + hi
+ override def kind = "TypeBoundsType"
+ }
+
+ object TypeBounds {
+ def empty: TypeBounds = apply(NothingClass.tpe, AnyClass.tpe)
+ def upper(hi: Type): TypeBounds = apply(NothingClass.tpe, hi)
+ def lower(lo: Type): TypeBounds = apply(lo, AnyClass.tpe)
+
+ def apply(lo: Type, hi: Type): TypeBounds =
+ unique(new TypeBounds(lo, hi) with UniqueType)
+ }
+
+ /** A common base class for intersection types and class types
+ */
+ abstract class CompoundType extends Type {
+
+ var baseTypeSeqCache: BaseTypeSeq = _
+ private var baseTypeSeqPeriod = NoPeriod
+ private var baseClassesCache: List[Symbol] = _
+ private var baseClassesPeriod = NoPeriod
+
+ override def baseTypeSeq: BaseTypeSeq = {
+ val period = baseTypeSeqPeriod;
+ if (period != currentPeriod) { // no caching in IDE
+ baseTypeSeqPeriod = currentPeriod
+ if (!isValidForBaseClasses(period)) {
+ if (parents.exists(_.exists(_.isInstanceOf[TypeVar]))) {
+ // rename type vars to fresh type params, take base type sequence of
+ // resulting type, and rename back all the entries in that sequence
+ var tvs = Set[TypeVar]()
+ for (p <- parents)
+ for (t <- p) t match {
+ case tv: TypeVar => tvs += tv
+ case _ =>
+ }
+ val varToParamMap: Map[Type, Symbol] = tvs map (tv => tv -> tv.origin.typeSymbol.cloneSymbol) toMap
+ val paramToVarMap = varToParamMap map (_.swap)
+ val varToParam = new TypeMap {
+ def apply(tp: Type) = varToParamMap get tp match {
+ case Some(sym) => sym.tpe
+ case _ => mapOver(tp)
+ }
+ }
+ val paramToVar = new TypeMap {
+ def apply(tp: Type) = tp match {
+ case TypeRef(_, tsym, _) if paramToVarMap.isDefinedAt(tsym) => paramToVarMap(tsym)
+ case _ => mapOver(tp)
+ }
+ }
+ val bts = copyRefinedType(this.asInstanceOf[RefinedType], parents map varToParam, varToParam mapOver decls).baseTypeSeq
+ baseTypeSeqCache = bts lateMap paramToVar
+ } else {
+ incCounter(compoundBaseTypeSeqCount)
+ baseTypeSeqCache = undetBaseTypeSeq
+ baseTypeSeqCache = if (typeSymbol.isRefinementClass)
+ memo(compoundBaseTypeSeq(this))(_.baseTypeSeq updateHead typeSymbol.tpe)
+ else
+ compoundBaseTypeSeq(this)
+ // [Martin] suppressing memo-ization solves the problem with "same type after erasure" errors
+ // when compiling with
+ // scalac scala.collection.IterableViewLike.scala scala.collection.IterableLike.scala
+ // I have not yet figured out precisely why this is the case.
+ // My current assumption is that taking memos forces baseTypeSeqs to be computed
+ // at stale types (i.e. the underlying typeSymbol has already another type).
+ // I do not yet see precisely why this would cause a problem, but it looks
+ // fishy in any case.
+ }
+ }
+ //Console.println("baseTypeSeq(" + typeSymbol + ") = " + baseTypeSeqCache.toList);//DEBUG
+ }
+ if (baseTypeSeqCache eq undetBaseTypeSeq)
+ throw new TypeError("illegal cyclic inheritance involving " + typeSymbol)
+ baseTypeSeqCache
+ }
+
+ override def baseTypeSeqDepth: Int = baseTypeSeq.maxDepth
+
+ override def baseClasses: List[Symbol] = {
+ def computeBaseClasses: List[Symbol] =
+ if (parents.isEmpty) List(typeSymbol)
+ else {
+ //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG
+ // optimized, since this seems to be performance critical
+ val superclazz = parents.head
+ var mixins = parents.tail
+ val sbcs = superclazz.baseClasses
+ var bcs = sbcs
+ def isNew(clazz: Symbol): Boolean = (
+ superclazz.baseTypeIndex(clazz) < 0 &&
+ { var p = bcs;
+ while ((p ne sbcs) && (p.head != clazz)) p = p.tail;
+ p eq sbcs
+ }
+ );
+ while (!mixins.isEmpty) {
+ def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] =
+ if (mbcs.isEmpty) bcs
+ else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail)
+ else addMixinBaseClasses(mbcs.tail);
+ bcs = addMixinBaseClasses(mixins.head.baseClasses)
+ mixins = mixins.tail
+ }
+ typeSymbol :: bcs
+ }
+ val period = baseClassesPeriod
+ if (period != currentPeriod) {
+ baseClassesPeriod = currentPeriod
+ if (!isValidForBaseClasses(period)) {
+ baseClassesCache = null
+ baseClassesCache = memo(computeBaseClasses)(typeSymbol :: _.baseClasses.tail)
+ }
+ }
+ if (baseClassesCache eq null)
+ throw new TypeError("illegal cyclic reference involving " + typeSymbol)
+ baseClassesCache
+ }
+
+ /** The slightly less idiomatic use of Options is due to
+ * performance considerations. A version using for comprehensions
+ * might be too slow (this is deemed a hotspot of the type checker).
+ *
+ * See with Martin before changing this method.
+ */
+ def memo[A](op1: => A)(op2: Type => A): A = {
+ def updateCache(): A = {
+ intersectionWitness(parents) = new WeakReference(this)
+ op1
+ }
+
+ intersectionWitness get parents match {
+ case Some(ref) =>
+ ref.get match {
+ case Some(w) => if (w eq this) op1 else op2(w)
+ case None => updateCache()
+ }
+ case None => updateCache()
+ }
+
+ }
+
+ override def baseType(sym: Symbol): Type = {
+ val index = baseTypeIndex(sym)
+ if (index >= 0) baseTypeSeq(index) else NoType
+ }
+
+ override def narrow: Type = typeSymbol.thisType
+ override def isNotNull: Boolean = parents exists (_.isNotNull)
+
+ override def isStructuralRefinement: Boolean =
+ typeSymbol.isAnonOrRefinementClass &&
+ (decls.toList exists { entry => !entry.isConstructor && entry.allOverriddenSymbols.isEmpty })
+
+ // override def isNullable: Boolean =
+ // parents forall (p => p.isNullable && !p.typeSymbol.isAbstractType);
+
+ override def safeToString: String =
+ parents.mkString(" with ") +
+ (if (settings.debug.value || parents.isEmpty || (decls.elems ne null))
+ decls.mkString("{", "; ", "}") else "")
+ }
+
+ /** A class representing intersection types with refinements of the form
+ * `<parents_0> with ... with <parents_n> { decls }'
+ * Cannot be created directly;
+ * one should always use `refinedType' for creation.
+ */
+ case class RefinedType(override val parents: List[Type],
+ override val decls: Scope) extends CompoundType {
+
+ override def isHigherKinded = (
+ parents.nonEmpty &&
+ (parents forall (_.isHigherKinded)) &&
+ !phase.erasedTypes // @MO to AM: please check this class!
+ )
+
+ override def typeParams =
+ if (isHigherKinded) parents.head.typeParams
+ else super.typeParams
+
+ //@M may result in an invalid type (references to higher-order args become dangling )
+ override def typeConstructor =
+ copyRefinedType(this, parents map (_.typeConstructor), decls)
+
+ private def dummyArgs = typeParams map (_.typeConstructor)
+
+ /* MO to AM: This is probably not correct
+ * If they are several higher-kinded parents with different bounds we need
+ * to take the intersection of their bounds
+ */
+ override def normalize = {
+ if (isHigherKinded) {
+ typeFun(
+ typeParams,
+ RefinedType(
+ parents map {
+ case TypeRef(pre, sym, List()) => TypeRef(pre, sym, dummyArgs)
+ case p => p
+ },
+ decls,
+ typeSymbol))
+ }
+ else super.normalize
+ }
+
+ /** A refined type P1 with ... with Pn { decls } is volatile if
+ * one of the parent types Pi is an abstract type, and
+ * either i > 1, or decls or a following parent Pj, j > 1, contributes
+ * an abstract member.
+ * A type contributes an abstract member if it has an abstract member which
+ * is also a member of the whole refined type. A scope `decls' contributes
+ * an abstract member if it has an abstract definition which is also
+ * a member of the whole type.
+ */
+ override def isVolatile = {
+ def isVisible(m: Symbol) =
+ this.nonPrivateMember(m.name).alternatives contains m
+ def contributesAbstractMembers(p: Type) =
+ p.deferredMembers exists isVisible
+
+ ((parents exists (_.isVolatile))
+ ||
+ (parents dropWhile (! _.typeSymbol.isAbstractType) match {
+ case ps @ (_ :: ps1) =>
+ (ps ne parents) ||
+ (ps1 exists contributesAbstractMembers) ||
+ (decls.iterator exists (m => m.isDeferred && isVisible(m)))
+ case _ =>
+ false
+ }))
+ }
+
+ override def kind = "RefinedType"
+ }
+
+ object RefinedType {
+ def apply(parents: List[Type], decls: Scope, clazz: Symbol) =
+ new RefinedType(parents, decls) { override def typeSymbol = clazz }
+ }
+
+ /** A class representing a class info
+ */
+ case class ClassInfoType(
+ override val parents: List[Type],
+ override val decls: Scope,
+ override val typeSymbol: Symbol) extends CompoundType
+ {
+
+ /** refs indices */
+ private final val NonExpansive = 0
+ private final val Expansive = 1
+
+ /** initialization states */
+ private final val UnInitialized = 0
+ private final val Initializing = 1
+ private final val Initialized = 2
+
+ private type RefMap = Map[Symbol, immutable.Set[Symbol]]
+
+ /** All type parameters reachable from given type parameter
+ * by a path which contains at least one expansive reference.
+ * @See Kennedy, Pierce: On Decidability of Nominal Subtyping with Variance
+ */
+ def expansiveRefs(tparam: Symbol) = {
+ if (state == UnInitialized) {
+ computeRefs()
+ while (state != Initialized) propagate()
+ }
+ getRefs(Expansive, tparam)
+ }
+
+ /* The rest of this class is auxiliary code for `expansiveRefs'
+ */
+
+ /** The type parameters which are referenced type parameters of this class.
+ * Two entries: refs(0): Non-expansive references
+ * refs(1): Expansive references
+ */
+ private var refs: Array[RefMap] = _
+
+ /** The initialization state of the class: UnInialized --> Initializing --> Initialized
+ */
+ private var state = UnInitialized
+
+ /** Get references for given type parameter
+ * @param which in {NonExpansive, Expansive}
+ * @param from The type parameter from which references originate.
+ */
+ private def getRefs(which: Int, from: Symbol): Set[Symbol] = refs(which) get from match {
+ case Some(set) => set
+ case none => Set()
+ }
+
+ /** Augment existing refs map with reference <pre>from -> to</pre>
+ * @param which <- {NonExpansive, Expansive}
+ */
+ private def addRef(which: Int, from: Symbol, to: Symbol) {
+ refs(which) = refs(which) + (from -> (getRefs(which, from) + to))
+ }
+
+ /** Augment existing refs map with references <pre>from -> sym</pre>, for
+ * all elements <pre>sym</pre> of set `to'.
+ * @param which <- {NonExpansive, Expansive}
+ */
+ private def addRefs(which: Int, from: Symbol, to: Set[Symbol]) {
+ refs(which) = refs(which) + (from -> (getRefs(which, from) ++ to))
+ }
+
+ /** The ClassInfoType which belongs to the class containing given type parameter
+ */
+ private def classInfo(tparam: Symbol): ClassInfoType =
+ tparam.owner.info.resultType match {
+ case ci: ClassInfoType => ci
+ case _ => classInfo(ObjectClass) // something's wrong; fall back to safe value
+ // (this can happen only for erroneous programs).
+ }
+
+ /** Compute initial (one-step) references and set state to `Initializing'.
+ */
+ private def computeRefs() {
+ refs = Array(Map(), Map())
+ for (tparam <- typeSymbol.typeParams) {
+ val enterRefs = new TypeMap {
+ def apply(tp: Type): Type = {
+ tp match {
+ case TypeRef(_, sym, args) =>
+ for ((tparam1, arg) <- sym.info.typeParams zip args)
+ if (arg contains tparam) {
+ addRef(NonExpansive, tparam, tparam1)
+ if (arg.typeSymbol != tparam) addRef(Expansive, tparam, tparam1)
+ }
+ case _ =>
+ }
+ mapOver(tp)
+ }
+ }
+ for (p <- parents) enterRefs(p)
+ }
+ state = Initializing
+ }
+
+ /** Propagate to form transitive closure.
+ * Set state to Initialized if no change resulted from propagation.
+ * @return true iff there as a change in last iteration
+ */
+ private def propagate(): Boolean = {
+ if (state == UnInitialized) computeRefs()
+ //Console.println("Propagate "+symbol+", initial expansive = "+refs(Expansive)+", nonexpansive = "+refs(NonExpansive))//DEBUG
+ val lastRefs = Array(refs(0), refs(1))
+ state = Initialized
+ var change = false
+ for ((from, targets) <- refs(NonExpansive).iterator)
+ for (target <- targets) {
+ var thatInfo = classInfo(target)
+ if (thatInfo.state != Initialized)
+ change = change | thatInfo.propagate()
+ addRefs(NonExpansive, from, thatInfo.getRefs(NonExpansive, target))
+ addRefs(Expansive, from, thatInfo.getRefs(Expansive, target))
+ }
+ for ((from, targets) <- refs(Expansive).iterator)
+ for (target <- targets) {
+ var thatInfo = classInfo(target)
+ if (thatInfo.state != Initialized)
+ change = change | thatInfo.propagate()
+ addRefs(Expansive, from, thatInfo.getRefs(NonExpansive, target))
+ }
+ change = change || refs(0) != lastRefs(0) || refs(1) != lastRefs(1)
+ if (change) state = Initializing
+ //else Console.println("Propagate "+symbol+", final expansive = "+refs(Expansive)+", nonexpansive = "+refs(NonExpansive))//DEBUG
+ change
+ }
+
+ // override def isNullable: Boolean =
+ // symbol == AnyClass ||
+ // symbol != NothingClass && (symbol isSubClass ObjectClass) && !(symbol isSubClass NonNullClass);
+
+ // override def isNonNull: Boolean = symbol == NonNullClass || super.isNonNull;
+ override def kind = "ClassInfoType"
+ }
+
+ class PackageClassInfoType(decls: Scope, clazz: Symbol)
+ extends ClassInfoType(List(), decls, clazz)
+
+ /** A class representing a constant type.
+ *
+ * @param value ...
+ */
+ abstract case class ConstantType(value: Constant) extends SingletonType {
+ override def underlying: Type = value.tpe
+ assert(underlying.typeSymbol != UnitClass)
+ override def isTrivial: Boolean = true
+ override def isNotNull = value.value != null
+ override def deconst: Type = underlying
+ override def safeToString: String =
+ underlying.toString + "(" + value.escapedStringValue + ")"
+ // override def isNullable: Boolean = value.value eq null
+ // override def isNonNull: Boolean = value.value ne null
+ override def kind = "ConstantType"
+ }
+
+ object ConstantType {
+ def apply(value: Constant): ConstantType = {
+ class UniqueConstantType extends ConstantType(value) with UniqueType {
+ /** Save the type of 'value'. For Java enums, it depends on finding the linked class,
+ * which might not be found after 'flatten'. */
+ private lazy val _tpe: Type = value.tpe
+ override def underlying: Type = _tpe
+ }
+ unique(new UniqueConstantType)
+ }
+ }
+
+ private var volatileRecursions: Int = 0
+ private val pendingVolatiles = new mutable.HashSet[Symbol]
+
+ /** A class for named types of the form
+ * `<prefix>.<sym.name>[args]'
+ * Cannot be created directly; one should always use `typeRef'
+ * for creation. (@M: Otherwise hashing breaks)
+ *
+ * @M: a higher-kinded type is represented as a TypeRef with sym.info.typeParams.nonEmpty, but args.isEmpty
+ * @param pre ...
+ * @param sym ...
+ * @param args ...
+ */
+ abstract case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type {
+// assert(!sym.isAbstractType || pre.isStable || pre.isError)
+// assert(!pre.isInstanceOf[ClassInfoType], this)
+// assert(!(sym hasFlag (PARAM | EXISTENTIAL)) || pre == NoPrefix, this)
+// assert(args.isEmpty || !sym.info.typeParams.isEmpty, this)
+// assert(args.isEmpty || ((sym ne AnyClass) && (sym ne NothingClass))
+
+ private val parentsCache = new ListOfTypesCache {
+ @inline final def calculate() = thisInfo.parents map transform
+ }
+ private var baseTypeSeqCache: BaseTypeSeq = _
+ private var baseTypeSeqPeriod = NoPeriod
+
+ override def isStable: Boolean = {
+ sym == NothingClass ||
+ sym == SingletonClass ||
+ sym.isAliasType && normalize.isStable ||
+ sym.isAbstractType && (bounds.hi.typeSymbol isSubClass SingletonClass)
+ }
+
+ override def isVolatile: Boolean = {
+ sym.isAliasType && normalize.isVolatile ||
+ sym.isAbstractType && {
+ // need to be careful not to fall into an infinite recursion here
+ // because volatile checking is done before all cycles are detected.
+ // the case to avoid is an abstract type directly or
+ // indirectly upper-bounded by itself. See #2918
+ try {
+ volatileRecursions += 1
+ if (volatileRecursions < LogVolatileThreshold)
+ bounds.hi.isVolatile
+ else if (pendingVolatiles(sym))
+ true // we can return true here, because a cycle will be detected
+ // here afterwards and an error will result anyway.
+ else
+ try {
+ pendingVolatiles += sym
+ bounds.hi.isVolatile
+ } finally {
+ pendingVolatiles -= sym
+ }
+ } finally {
+ volatileRecursions -= 1
+ }
+ }
+ }
+
+ override lazy val isTrivial: Boolean =
+ !sym.isTypeParameter && pre.isTrivial && args.forall(_.isTrivial)
+
+ override def isNotNull =
+ sym.isModuleClass || sym == NothingClass || isValueClass(sym) || super.isNotNull
+
+ // @M: propagate actual type params (args) to `tp', by replacing formal type parameters with actual ones
+ // if tp is higher kinded, the "actual" type arguments are types that simply reference the corresponding type parameters (unbound type variables)
+ def transform(tp: Type): Type = {
+ val res = tp.asSeenFrom(pre, sym.owner)
+ if (sym.typeParams.isEmpty || (args exists (_.isError)) || isRaw(sym, args)/*#2266/2305*/) res
+ else res.instantiateTypeParams(sym.typeParams, typeArgsOrDummies)
+ }
+
+ //@M! use appliedType on the polytype that represents the bounds (or if aliastype, the rhs)
+ def transformInfo(tp: Type): Type = appliedType(tp.asSeenFrom(pre, sym.owner), typeArgsOrDummies)
+
+ def thisInfo =
+ if (sym.isAliasType) normalize
+ else if (sym.isNonClassType) transformInfo(sym.info)
+ else sym.info
+
+ def relativeInfo = if (sym.isNonClassType) transformInfo(pre.memberInfo(sym)) else pre.memberInfo(sym)
+
+ override def typeSymbol = if (sym.isAliasType) normalize.typeSymbol else sym
+ override def termSymbol = if (sym.isAliasType) normalize.termSymbol else super.termSymbol
+ override def typeSymbolDirect = sym
+ override def termSymbolDirect = super.termSymbol
+
+/* @MAT
+whenever you see `tp.typeSymbol.isXXXX' and then act on tp based on that predicate, you're on thin ice,
+as `typeSymbol' (and `prefix') automatically normalize, but the other inspectors don't.
+In other words, even if `tp.normalize.sym.isXXX' is true, `tp.sym.isXXX' may be false (if sym were a public method to access the non-normalized typeSymbol)...
+
+In retrospect, I think `tp.typeSymbol.isXXX' or (worse) `tp.typeSymbol==XXX' should be replaced by `val tp = tp0.asXXX'.
+A type's typeSymbol should never be inspected directly.
+*/
+
+ override def bounds: TypeBounds =
+ if (sym.isAbstractType) thisInfo.bounds // transform(thisInfo.bounds).asInstanceOf[TypeBounds] // ??? seems to be doing asSeenFrom twice
+ else super.bounds
+
+ override def parents: List[Type] = parentsCache.get()
+ override def typeOfThis = transform(sym.typeOfThis)
+
+/*
+ override def narrow =
+ if (sym.isModuleClass) transform(sym.thisType)
+ else if (sym.isAliasType) normalize.narrow
+ else super.narrow
+*/
+ override def narrow =
+ if (sym.isModuleClass) singleType(pre, sym.sourceModule)
+ else if (sym.isAliasType) normalize.narrow
+ else super.narrow
+
+ override def prefix: Type =
+ if (sym.isAliasType) normalize.prefix
+ else pre
+
+ override def typeArgs: List[Type] = args
+ private def typeArgsOrDummies = if (!isHigherKinded) args else dummyArgs
+
+ // @MAT was typeSymbol.unsafeTypeParams, but typeSymbol normalizes now
+ private def typeParamsDirect =
+ if (isDefinitionsInitialized) sym.typeParams
+ else sym.unsafeTypeParams
+
+ // placeholders derived from type params
+ private def dummyArgs = typeParamsDirect map (_.typeConstructor) //@M must be .typeConstructor
+
+ // (!result.isEmpty) IFF isHigherKinded
+ override def typeParams: List[Symbol] = if (isHigherKinded) typeParamsDirect else List()
+
+ override def typeConstructor = TypeRef(pre, sym, Nil)
+ // note: does not go through typeRef. There's no need to because neither `pre' nor `sym' changes.
+ // And there's a performance advantage to call TypeRef directly.
+
+
+ // a reference (in a Scala program) to a type that has type parameters, but where the reference does not include type arguments
+ // note that it doesn't matter whether the symbol refers to a java or scala symbol,
+ // it does matter whether it occurs in java or scala code
+ // typerefs w/o type params that occur in java signatures/code are considered raw types, and are represented as existential types
+ override def isHigherKinded = args.isEmpty && typeParamsDirect.nonEmpty
+
+ override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type =
+ if (isHigherKinded) {
+ val substTps = formals.intersect(typeParams)
+
+ if (sameLength(substTps, typeParams))
+ typeRef(pre, sym, actuals)
+ else if (sameLength(formals, actuals)) // partial application (needed in infer when bunching type arguments from classes and methods together)
+ typeRef(pre, sym, dummyArgs).subst(formals, actuals)
+ else ErrorType
+ }
+ else
+ super.instantiateTypeParams(formals, actuals)
+
+
+ private var normalized: Type = null
+
+ @inline private def betaReduce: Type = {
+ assert(sameLength(sym.info.typeParams, typeArgs), this)
+ // isHKSubType0 introduces synthetic type params so that betaReduce can first apply sym.info to typeArgs before calling asSeenFrom
+ // asSeenFrom then skips synthetic type params, which are used to reduce HO subtyping to first-order subtyping, but which can't be instantiated from the given prefix and class
+ // appliedType(sym.info, typeArgs).asSeenFrom(pre, sym.owner) // this crashes pos/depmet_implicit_tpbetareduce.scala
+ transform(sym.info.resultType)
+ }
+
+ // @M: initialize (by sym.info call) needed (see test/files/pos/ticket0137.scala)
+ @inline private def etaExpand: Type = {
+ val tpars = sym.info.typeParams // must go through sym.info for typeParams to initialise symbol
+ typeFunAnon(tpars, typeRef(pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
+ }
+
+ override def dealias: Type =
+ if (sym.isAliasType && sameLength(sym.info.typeParams, args)) {
+ betaReduce.dealias
+ } else this
+
+ def normalize0: Type =
+ if (pre eq WildcardType) WildcardType // arises when argument-dependent types are approximated (see def depoly in implicits)
+ else if (isHigherKinded) etaExpand // eta-expand, subtyping relies on eta-expansion of higher-kinded types
+ else if (sym.isAliasType && sameLength(sym.info.typeParams, args))
+ betaReduce.normalize // beta-reduce, but don't do partial application -- cycles have been checked in typeRef
+ else if (sym.isRefinementClass)
+ sym.info.normalize // I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers
+ else {
+ if(sym.isAliasType) ErrorType //println("!!error: "+(pre, sym, sym.info, sym.info.typeParams, args))
+ else super.normalize
+ }
+
+ // TODO: test case that is compiled in a specific order and in different runs
+ override def normalize: Type = {
+ if (phase.erasedTypes) normalize0
+ else {
+ if (normalized == null)
+ normalized = normalize0
+
+ normalized
+ }
+ }
+
+ override def decls: Scope = {
+ sym.info match {
+ case TypeRef(_, sym1, _) =>
+ assert(sym1 != sym, this) // @MAT was != typeSymbol
+ case _ =>
+ }
+ thisInfo.decls
+ }
+
+ override def baseType(clazz: Symbol): Type =
+ if (sym == clazz) this
+ else if (sym.isClass) transform(sym.info.baseType(clazz))
+ else
+ try {
+ basetypeRecursions += 1
+ if (basetypeRecursions < LogPendingBaseTypesThreshold)
+ relativeInfo.baseType(clazz)
+ else if (pendingBaseTypes contains this)
+ if (clazz == AnyClass) clazz.tpe else NoType
+ else
+ try {
+ pendingBaseTypes += this
+ relativeInfo.baseType(clazz)
+ } finally {
+ pendingBaseTypes -= this
+ }
+ } finally {
+ basetypeRecursions -= 1
+ }
+
+ override def baseTypeSeq: BaseTypeSeq = {
+ val period = baseTypeSeqPeriod
+ if (period != currentPeriod) {
+ baseTypeSeqPeriod = currentPeriod
+ if (!isValidForBaseClasses(period)) {
+ incCounter(typerefBaseTypeSeqCount)
+ baseTypeSeqCache = undetBaseTypeSeq
+ baseTypeSeqCache =
+ if (sym.isAbstractType) transform(bounds.hi).baseTypeSeq prepend this
+ else sym.info.baseTypeSeq map transform
+ }
+ }
+ if (baseTypeSeqCache == undetBaseTypeSeq)
+ throw new TypeError("illegal cyclic inheritance involving " + sym)
+ baseTypeSeqCache
+ }
+
+ override def baseTypeSeqDepth: Int = baseTypeSeq.maxDepth
+
+ override def baseClasses: List[Symbol] = thisInfo.baseClasses
+
+ // override def isNullable: Boolean = sym.info.isNullable
+
+ override def safeToString: String = {
+ if (!settings.debug.value) {
+ this match {
+ case TypeRef(_, RepeatedParamClass, arg :: _) => return arg + "*"
+ case TypeRef(_, ByNameParamClass, arg :: _) => return "=> " + arg
+ case _ =>
+ if (isFunctionType(this))
+ return normalize.typeArgs.init.mkString("(", ", ", ")") + " => " + normalize.typeArgs.last
+ else if (isTupleTypeOrSubtype(this))
+ return normalize.typeArgs.mkString("(", ", ", if (hasLength(normalize.typeArgs, 1)) ",)" else ")")
+ else if (sym.isAliasType && prefixChain.exists(_.termSymbol.isSynthetic)) {
+ val normed = normalize;
+ if (normed ne this) return normed.toString
+ }
+ }
+ }
+ val monopart =
+ if (!settings.debug.value &&
+ (shorthands contains sym.fullName) &&
+ (sym.ownerChain forall (_.isClass))) // ensure that symbol is not a local copy with a name coincidence
+ sym.name.toString
+ else
+ pre.prefixString + sym.nameString
+
+ var str = monopart + (if (args.isEmpty) "" else args.mkString("[", ",", "]"))
+ if (sym.isPackageClass)
+ packagePrefix + str
+ else if (sym.isModuleClass)
+ objectPrefix + str
+ else if (sym.isAnonymousClass && sym.isInitialized && !settings.debug.value && !phase.erasedTypes)
+ thisInfo.parents.mkString(" with ") + {
+ if (sym.isStructuralRefinement)
+ ((decls.toList filter { entry =>
+ !entry.isConstructor && entry.allOverriddenSymbols.isEmpty && !entry.isPrivate
+ }) map { entry => entry.defString }).mkString("{", "; ", "}")
+ else
+ ""
+ }
+ else if (sym.isRefinementClass && sym.isInitialized)
+ thisInfo.toString
+ else str
+ }
+
+ override def prefixString = "" + (
+ if (settings.debug.value)
+ super.prefixString
+ else if (sym.printWithoutPrefix)
+ ""
+ else if (sym.isPackageClass)
+ sym.fullName + "."
+ else if (isStable && nme.isSingletonName(sym.name))
+ nme.dropSingletonName(sym.name) + "."
+ else
+ super.prefixString
+ )
+ override def kind = "TypeRef"
+ }
+
+ object TypeRef {
+ def apply(pre: Type, sym: Symbol, args: List[Type]): Type = {
+ unique(new TypeRef(pre, sym, args) with UniqueType)
+ }
+ }
+
+ /** A class representing a method type with parameters.
+ * Note that a parameterless method is represented by a NullaryMethodType:
+ *
+ * def m(): Int MethodType(Nil, Int)
+ * def m: Int NullaryMethodType(Int)
+ */
+ case class MethodType(override val params: List[Symbol],
+ override val resultType: Type) extends Type {
+ override def isTrivial: Boolean = isTrivial0
+ private lazy val isTrivial0 =
+ resultType.isTrivial && params.forall{p => p.tpe.isTrivial && (
+ !settings.YdepMethTpes.value || !(params.exists(_.tpe.contains(p)) || resultType.contains(p)))
+ }
+
+ def isImplicit = params.nonEmpty && params.head.isImplicit
+ def isJava = false // can we do something like for implicits? I.e. do Java methods without parameters need to be recognized?
+
+ //assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG
+ override def paramSectionCount: Int = resultType.paramSectionCount + 1
+
+ override def paramss: List[List[Symbol]] = params :: resultType.paramss
+
+ override def paramTypes = params map (_.tpe)
+
+ override def boundSyms = immutable.Set[Symbol](params ++ resultType.boundSyms: _*)
+
+ // AM to TR: #dropNonContraintAnnotations
+ // this is needed for plugins to work correctly, only TypeConstraint annotations are supposed to be carried over
+ // TODO: this should probably be handled in a more structured way in adapt -- remove this map in resultType and watch the continuations tests fail
+ object dropNonContraintAnnotations extends TypeMap {
+ override val dropNonConstraintAnnotations = true
+ def apply(x: Type) = mapOver(x)
+ }
+
+ override def resultType(actuals: List[Type]) =
+ if (isTrivial) dropNonContraintAnnotations(resultType)
+ else {
+ if (sameLength(actuals, params)) {
+ val idm = new InstantiateDependentMap(params, actuals)
+ val res = idm(resultType)
+ // println("resultTypeDep "+(params, actuals, resultType, idm.existentialsNeeded, "\n= "+ res))
+ existentialAbstraction(idm.existentialsNeeded, res)
+ } else {
+ // Thread.dumpStack()
+ // println("resultType "+(params, actuals, resultType))
+ if (phase.erasedTypes) resultType
+ else existentialAbstraction(params, resultType)
+ }
+ }
+
+ // implicit args can only be depended on in result type: TODO this may be generalised so that the only constraint is dependencies are acyclic
+ def approximate: MethodType = MethodType(params, resultApprox)
+
+ override def finalResultType: Type = resultType.finalResultType
+
+ override def safeToString = paramString(this) + resultType
+
+ override def cloneInfo(owner: Symbol) = {
+ val vparams = cloneSymbols(params, owner)
+ copyMethodType(this, vparams, resultType.substSym(params, vparams).cloneInfo(owner))
+ }
+
+ override def atOwner(owner: Symbol) =
+ if ((params exists (_.owner != owner)) || (resultType.atOwner(owner) ne resultType))
+ cloneInfo(owner)
+ else
+ this
+
+ override def kind = "MethodType"
+ }
+
+ class JavaMethodType(ps: List[Symbol], rt: Type) extends MethodType(ps, rt) {
+ override def isJava = true
+ }
+
+ case class NullaryMethodType(override val resultType: Type) extends Type {
+ // AM to TR: #dropNonContraintAnnotations
+ // change isTrivial to the commented version and watch continuations-run/t3225.scala fail
+ // isTrivial implies asSeenFrom is bypassed, since it's supposed to be the identity map
+ // it's not really the identity due to dropNonContraintAnnotations
+ override def isTrivial: Boolean = false //resultType.isTrivial -- `false` to make continuations plugin work (so that asSeenFromMap drops non-constrain annotations even when type doesn't change otherwise)
+ override def prefix: Type = resultType.prefix
+ override def narrow: Type = resultType.narrow
+ override def finalResultType: Type = resultType.finalResultType
+ override def termSymbol: Symbol = resultType.termSymbol
+ override def typeSymbol: Symbol = resultType.typeSymbol
+ override def parents: List[Type] = resultType.parents
+ override def decls: Scope = resultType.decls
+ override def baseTypeSeq: BaseTypeSeq = resultType.baseTypeSeq
+ override def baseTypeSeqDepth: Int = resultType.baseTypeSeqDepth
+ override def baseClasses: List[Symbol] = resultType.baseClasses
+ override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
+ override def boundSyms = resultType.boundSyms
+ override def isVolatile = resultType.isVolatile
+ override def safeToString: String = "=> "+ resultType
+ override def kind = "NullaryMethodType"
+ }
+
+ /** A type function or the type of a polymorphic value (and thus of kind *).
+ *
+ * Before the introduction of NullaryMethodType, a polymorphic nullary method (e.g, def isInstanceOf[T]: Boolean)
+ * used to be typed as PolyType(tps, restpe), and a monomorphic one as PolyType(Nil, restpe)
+ * This is now: PolyType(tps, NullaryMethodType(restpe)) and NullaryMethodType(restpe)
+ * by symmetry to MethodTypes: PolyType(tps, MethodType(params, restpe)) and MethodType(params, restpe)
+ *
+ * Thus, a PolyType(tps, TypeRef(...)) unambiguously indicates a type function (which results from eta-expanding a type constructor alias).
+ * Similarly, PolyType(tps, ClassInfoType(...)) is a type constructor.
+ *
+ * A polytype is of kind * iff its resultType is a (nullary) method type.
+ */
+ case class PolyType(override val typeParams: List[Symbol], override val resultType: Type)
+ extends Type {
+ //assert(!(typeParams contains NoSymbol), this)
+ assert(typeParams nonEmpty, this) // used to be a marker for nullary method type, illegal now (see @NullaryMethodType)
+
+ override def paramSectionCount: Int = resultType.paramSectionCount
+ override def paramss: List[List[Symbol]] = resultType.paramss
+ override def params: List[Symbol] = resultType.params
+ override def paramTypes: List[Type] = resultType.paramTypes
+ override def parents: List[Type] = resultType.parents
+ override def decls: Scope = resultType.decls
+ override def termSymbol: Symbol = resultType.termSymbol
+ override def typeSymbol: Symbol = resultType.typeSymbol
+ override def boundSyms = immutable.Set[Symbol](typeParams ++ resultType.boundSyms: _*)
+ override def prefix: Type = resultType.prefix
+ override def baseTypeSeq: BaseTypeSeq = resultType.baseTypeSeq
+ override def baseTypeSeqDepth: Int = resultType.baseTypeSeqDepth
+ override def baseClasses: List[Symbol] = resultType.baseClasses
+ override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
+ override def narrow: Type = resultType.narrow
+ override def isVolatile = resultType.isVolatile
+ override def finalResultType: Type = resultType.finalResultType
+
+ /** @M: typeDefSig wraps a TypeBounds in a PolyType
+ * to represent a higher-kinded type parameter
+ * wrap lo&hi in polytypes to bind variables
+ */
+ override def bounds: TypeBounds =
+ TypeBounds(typeFun(typeParams, resultType.bounds.lo),
+ typeFun(typeParams, resultType.bounds.hi))
+
+ override def isHigherKinded = !typeParams.isEmpty
+
+ override def safeToString = typeParamsString(this) + resultType
+
+ override def cloneInfo(owner: Symbol) = {
+ val tparams = cloneSymbols(typeParams, owner)
+ PolyType(tparams, resultType.substSym(typeParams, tparams).cloneInfo(owner))
+ }
+
+ override def atOwner(owner: Symbol) =
+ if ((typeParams exists (_.owner != owner)) || (resultType.atOwner(owner) ne resultType))
+ cloneInfo(owner)
+ else
+ this
+
+ override def kind = "PolyType"
+ }
+
+ case class ExistentialType(quantified: List[Symbol],
+ override val underlying: Type) extends RewrappingTypeProxy
+ {
+ override protected def rewrap(newtp: Type) = existentialAbstraction(quantified, newtp)
+
+ override def isTrivial = false
+ override def isStable: Boolean = false
+ override def bounds = TypeBounds(maybeRewrap(underlying.bounds.lo), maybeRewrap(underlying.bounds.hi))
+ override def parents = underlying.parents map maybeRewrap
+ override def boundSyms = quantified.toSet
+ override def prefix = maybeRewrap(underlying.prefix)
+ override def typeArgs = underlying.typeArgs map maybeRewrap
+ override def params = underlying.params mapConserve { param =>
+ val tpe1 = rewrap(param.tpe)
+ if (tpe1 eq param.tpe) param else param.cloneSymbol.setInfo(tpe1)
+ }
+ override def paramTypes = underlying.paramTypes map maybeRewrap
+ override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = {
+// maybeRewrap(underlying.instantiateTypeParams(formals, actuals))
+
+ val quantified1 = new SubstTypeMap(formals, actuals) mapOver quantified
+ val underlying1 = underlying.instantiateTypeParams(formals, actuals)
+ if ((quantified1 eq quantified) && (underlying1 eq underlying)) this
+ else existentialAbstraction(quantified1, underlying1.substSym(quantified, quantified1))
+
+ }
+ override def baseType(clazz: Symbol) = maybeRewrap(underlying.baseType(clazz))
+ override def baseTypeSeq = underlying.baseTypeSeq map maybeRewrap
+ override def isHigherKinded = false
+
+ override def skolemizeExistential(owner: Symbol, origin: AnyRef) = {
+ def mkSkolem(tparam: Symbol): Symbol = {
+ val skolem = new TypeSkolem(
+ if (owner == NoSymbol) tparam.owner else owner,
+ tparam.pos, tparam.name.toTypeName, origin)
+ skolem.setInfo(tparam.info.cloneInfo(skolem))
+ .setFlag(tparam.flags | EXISTENTIAL)
+ .resetFlag(PARAM)
+ }
+ val skolems = quantified map mkSkolem
+ for (skolem <- skolems)
+ skolem setInfo skolem.info.substSym(quantified, skolems)
+ underlying.substSym(quantified, skolems)
+ }
+
+ private def wildcardArgsString(available: Set[Symbol], args: List[Type]): List[String] = args match {
+ case TypeRef(_, sym, _) :: args1 if (available contains sym) =>
+ ("_"+sym.infoString(sym.info)) :: wildcardArgsString(available - sym, args1)
+ case arg :: args1 if !(quantified exists (arg contains _)) =>
+ arg.toString :: wildcardArgsString(available, args1)
+ case _ =>
+ List()
+ }
+
+ override def safeToString: String = {
+ if (!(quantified exists (_.isSingletonExistential)) && !settings.debug.value)
+ // try to represent with wildcards first
+ underlying match {
+ case TypeRef(pre, sym, args) if args.nonEmpty =>
+ val wargs = wildcardArgsString(quantified.toSet, args)
+ if (sameLength(wargs, args))
+ return TypeRef(pre, sym, List()) + wargs.mkString("[", ", ", "]")
+ case _ =>
+ }
+ var ustr = underlying.toString
+ underlying match {
+ case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) => ustr = "("+ustr+")"
+ case _ =>
+ }
+ val str =
+ ustr+(quantified map (_.existentialToString) mkString(" forSome { ", "; ", " }"))
+ if (settings.explaintypes.value) "("+str+")" else str
+ }
+
+ override def cloneInfo(owner: Symbol) = {
+ val tparams = cloneSymbols(quantified, owner)
+ ExistentialType(tparams, underlying.substSym(quantified, tparams))
+ }
+
+ override def atOwner(owner: Symbol) =
+ if (quantified exists (_.owner != owner)) cloneInfo(owner) else this
+
+ override def kind = "ExistentialType"
+
+ def withTypeVars(op: Type => Boolean): Boolean = withTypeVars(op, AnyDepth)
+
+ def withTypeVars(op: Type => Boolean, depth: Int): Boolean = {
+ val quantifiedFresh = cloneSymbols(quantified)
+ val tvars = quantifiedFresh map (tparam => TypeVar(tparam))
+ val underlying1 = underlying.instantiateTypeParams(quantified, tvars) // fuse subst quantified -> quantifiedFresh -> tvars
+ op(underlying1) && {
+ solve(tvars, quantifiedFresh, quantifiedFresh map (x => 0), false, depth) &&
+ isWithinBounds(NoPrefix, NoSymbol, quantifiedFresh, tvars map (_.constr.inst))
+ }
+ }
+ }
+
+ /** A class containing the alternatives and type prefix of an overloaded symbol.
+ * Not used after phase `typer'.
+ */
+ case class OverloadedType(pre: Type, alternatives: List[Symbol]) extends Type {
+ override def prefix: Type = pre
+ override def safeToString =
+ (alternatives map pre.memberType).mkString("", " <and> ", "")
+ override def kind = "OverloadedType"
+ }
+
+ /** A class remembering a type instantiation for some a set of overloaded
+ * polymorphic symbols.
+ * Not used after phase `typer'.
+ */
+ case class AntiPolyType(pre: Type, targs: List[Type]) extends Type {
+ override def safeToString =
+ pre.toString + targs.mkString("(with type arguments ", ",", ")");
+ override def memberType(sym: Symbol) = appliedType(pre.memberType(sym), targs)
+// override def memberType(sym: Symbol) = pre.memberType(sym) match {
+// case PolyType(tparams, restp) =>
+// restp.subst(tparams, targs)
+// /* I don't think this is needed, as existential types close only over value types
+// case ExistentialType(tparams, qtpe) =>
+// existentialAbstraction(tparams, qtpe.memberType(sym))
+// */
+// case ErrorType =>
+// ErrorType
+// }
+ override def kind = "AntiPolyType"
+ }
+
+ //private var tidCount = 0 //DEBUG
+
+ //@M
+ // a TypeVar used to be a case class with only an origin and a constr
+ // then, constr became mutable (to support UndoLog, I guess), but pattern-matching returned the original constr0 (a bug)
+ // now, pattern-matching returns the most recent constr
+ object TypeVar {
+ // encapsulate suspension so we can automatically link the suspension of cloned typevars to their original if this turns out to be necessary
+ def Suspension = new Suspension
+ class Suspension {
+ private val suspended = mutable.HashSet[TypeVar]()
+ def suspend(tv: TypeVar): Unit = {
+ tv.suspended = true
+ suspended += tv
+ }
+ def resumeAll(): Unit = {
+ for(tv <- suspended) {
+ tv.suspended = false
+ }
+ suspended.clear
+ }
+ }
+
+ def unapply(tv: TypeVar): Some[(Type, TypeConstraint)] = Some((tv.origin, tv.constr))
+ def apply(origin: Type, constr: TypeConstraint) = new TypeVar(origin, constr, List(), List())
+ def apply(tparam: Symbol) = new TypeVar(tparam.tpeHK, new TypeConstraint, List(), tparam.typeParams) // TODO why not initialise TypeConstraint with bounds of tparam?
+ def apply(origin: Type, constr: TypeConstraint, args: List[Type], params: List[Symbol]) = new TypeVar(origin, constr, args, params)
+ }
+
+ /** A class representing a type variable
+ * Not used after phase `typer'.
+ * A higher-kinded type variable has type arguments (a list of Type's) and type parameters (list of Symbols)
+ * A TypeVar whose list of args is non-empty can only be instantiated by a higher-kinded type that can be applied to these args
+ * a typevar is much like a typeref, except it has special logic for type equality/subtyping
+ */
+ class TypeVar(val origin: Type, val constr0: TypeConstraint, override val typeArgs: List[Type], override val params: List[Symbol]) extends Type {
+ // params are needed to keep track of variance (see mapOverArgs in SubstMap)
+ assert(typeArgs.isEmpty || sameLength(typeArgs, params))
+ // var tid = { tidCount += 1; tidCount } //DEBUG
+
+ /** The constraint associated with the variable */
+ var constr = constr0
+ def instValid = constr.instValid
+
+ /** The variable's skolemization level */
+ val level = skolemizationLevel
+
+ /**
+ * two occurrences of a higher-kinded typevar, e.g. ?CC[Int] and ?CC[String], correspond to
+ * *two instances* of TypeVar that share the *same* TypeConstraint
+ * constr for ?CC only tracks type constructors anyway, so when ?CC[Int] <:< List[Int] and ?CC[String] <:< Iterable[String]
+ * ?CC's hibounds contains List and Iterable
+ */
+ def applyArgs(newArgs: List[Type]): TypeVar =
+ if (newArgs.isEmpty) this // SubstMap relies on this (though this check is redundant when called from appliedType...)
+ else TypeVar(origin, constr, newArgs, params) // @M TODO: interaction with undoLog??
+ // newArgs.length may differ from args.length (could've been empty before)
+ // example: when making new typevars, you start out with C[A], then you replace C by ?C, which should yield ?C[A], then A by ?A, ?C[?A]
+ // we need to track a TypeVar's arguments, and map over them (see TypeMap::mapOver)
+ // TypeVars get applied to different arguments over time (in asSeenFrom)
+ // -- see pos/tcpoly_infer_implicit_tuplewrapper.scala
+ // thus: make new TypeVar's for every application of a TV to args,
+ // inference may generate several TypeVar's for a single type parameter that must be inferred,
+ // only one of them is in the set of tvars that need to be solved, but
+ // they share the same TypeConstraint instance
+
+ // <region name="constraint mutators + undoLog">
+ // invariant: before mutating constr, save old state in undoLog (undoLog is used to reset constraints to avoid piling up unrelated ones)
+ def setInst(tp: Type) {
+// assert(!(tp containsTp this), this)
+ undoLog record this
+ constr.inst = tp
+ }
+
+ def addLoBound(tp: Type, isNumericBound: Boolean = false) {
+ assert(tp != this) // implies there is a cycle somewhere (?)
+ //println("addLoBound: "+(safeToString, debugString(tp))) //DEBUG
+ undoLog record this
+ constr.addLoBound(tp, isNumericBound)
+ }
+
+ def addHiBound(tp: Type, isNumericBound: Boolean = false) {
+ // assert(tp != this)
+ //println("addHiBound: "+(safeToString, debugString(tp))) //DEBUG
+ undoLog record this
+ constr.addHiBound(tp, isNumericBound)
+ }
+ // </region>
+
+ // ignore subtyping&equality checks while true -- see findMember
+ private[TypeVar] var suspended = false
+
+ /** Called when a TypeVar is involved in a subtyping check. Result is whether
+ * this TypeVar could plausibly be a [super/sub]type of argument `tp` and if so,
+ * tracks tp as a [lower/upper] bound of this TypeVar.
+ *
+ * if (isLowerBound) this typevar could be a subtype, track tp as a lower bound
+ * if (!isLowerBound) this typevar could be a supertype, track tp as an upper bound
+ *
+ * If isNumericBound is true, the subtype check is performed with weak_<:< instead of <:<.
+ */
+ def registerBound(tp: Type, isLowerBound: Boolean, isNumericBound: Boolean = false): Boolean = {
+ // println("regBound: "+(safeToString, debugString(tp), isLowerBound)) //@MDEBUG
+ if (isLowerBound) assert(tp != this)
+
+ def checkSubtypeLower(tp1: Type, tp2: Type) =
+ if (isNumericBound) tp1 weak_<:< tp2
+ else tp1 <:< tp2
+
+ // swaps the arguments if it's an upper bound
+ def checkSubtype(tp1: Type, tp2: Type) =
+ if (isLowerBound) checkSubtypeLower(tp1, tp2)
+ else checkSubtypeLower(tp2, tp1)
+
+ def addBound(tp: Type) = {
+ if (isLowerBound) addLoBound(tp, isNumericBound)
+ else addHiBound(tp, isNumericBound)
+ // println("addedBound: "+(this, tp)) // @MDEBUG
+ true
+ }
+
+ /** Simple case: type arguments can be ignored, because either this typevar has
+ * no type parameters, or we are comparing to Any/Nothing.
+ *
+ * The latter condition is needed because HK unification is limited to constraints of the shape
+ * TC1[T1,..., TN] <: TC2[T'1,...,T'N]
+ * which would preclude the following important constraints:
+ * Nothing <: ?TC[?T]
+ * ?TC[?T] <: Any
+ */
+ def unifySimple = (params.isEmpty || tp.typeSymbol == NothingClass || tp.typeSymbol == AnyClass) &&
+ addBound(tp)
+
+ /** Full case: involving a check of the form
+ * TC1[T1,..., TN] <: TC2[T'1,...,T'N]
+ * Checks subtyping of higher-order type vars, and uses variances as defined in the
+ * type parameter we're trying to infer (the result will be sanity-checked later)
+ */
+ def unifyFull(tp: Type) = sameLength(typeArgs, tp.typeArgs) && { // this is a higher-kinded type var with same arity as tp
+ // side effect: adds the type constructor itself as a bound
+ addBound(tp.typeConstructor)
+ if (isLowerBound) isSubArgs(tp.typeArgs, typeArgs, params)
+ else isSubArgs(typeArgs, tp.typeArgs, params)
+ }
+
+ /** TODO: need positive/negative test cases demonstrating this is correct.
+ */
+ def unifyParents =
+ if (isLowerBound) tp.parents exists unifyFull
+ else tp.parents forall unifyFull
+
+ // TODO: fancier unification, maybe rewrite constraint as follows?
+ // val sym = constr.hiBounds map {_.typeSymbol} find { _.typeParams.length == typeArgs.length}
+ // this <: tp.baseType(sym)
+ if (suspended) checkSubtype(tp, origin)
+ else if (constr.instValid) checkSubtype(tp, constr.inst) // type var is already set
+ else isRelatable(tp) && {
+ unifySimple || unifyFull(tp) || unifyFull(tp.dealias) || unifyFull(tp.widen) || unifyParents
+ }
+ }
+
+ def registerTypeEquality(tp: Type, typeVarLHS: Boolean): Boolean = { //println("regTypeEq: "+(safeToString, debugString(tp), typeVarLHS)) //@MDEBUG
+ def checkIsSameType(tp: Type) =
+ if(typeVarLHS) constr.inst =:= tp
+ else tp =:= constr.inst
+
+ if (suspended) tp =:= origin
+ else if (constr.instValid) checkIsSameType(tp)
+ else isRelatable(tp) && {
+ val newInst = wildcardToTypeVarMap(tp)
+ if (constr.isWithinBounds(newInst)) {
+ setInst(tp)
+ true
+ } else false
+ }
+ }
+
+ /**
+ * ?A.T =:= tp is rewritten as the constraint ?A <: {type T = tp}
+ *
+ * TODO: make these constraints count (incorporate them into implicit search in applyImplicitArgs)
+ * (T corresponds to @param sym)
+ */
+ def registerTypeSelection(sym: Symbol, tp: Type): Boolean = {
+ val bound = refinedType(List(WildcardType), NoSymbol)
+ val bsym = bound.typeSymbol.newAliasType(NoPosition, sym.name.toTypeName)
+ bsym setInfo tp
+ bound.decls enter bsym
+ registerBound(bound, false)
+ }
+
+ /** Can this variable be related in a constraint to type `tp'?
+ * This is not the case if `tp' contains type skolems whose
+ * skolemization level is higher than the level of this variable.
+ */
+ def isRelatable(tp: Type): Boolean =
+ !tp.exists { t =>
+ t.typeSymbol match {
+ case ts: TypeSkolem => ts.level > level
+ case _ => false
+ }
+ }
+
+ override val isHigherKinded = typeArgs.isEmpty && params.nonEmpty
+
+ override def normalize: Type =
+ if (constr.instValid) constr.inst
+ // get here when checking higher-order subtyping of the typevar by itself
+ // TODO: check whether this ever happens?
+ else if (isHigherKinded) typeFun(params, applyArgs(params map (_.typeConstructor)))
+ else super.normalize
+
+ override def typeSymbol = origin.typeSymbol
+ override def isStable = origin.isStable
+ override def isVolatile = origin.isVolatile
+
+ private def levelString = if (settings.explaintypes.value) level else ""
+ override def safeToString = constr.inst match {
+ case null => "<null " + origin + ">"
+ case NoType => "?" + levelString + origin + typeArgsString(this)
+ case x => "" + x
+ }
+ override def kind = "TypeVar"
+
+ def cloneInternal = {
+ // cloning a suspended type variable when it's suspended will cause the clone
+ // to never be resumed with the current implementation
+ assert(!suspended)
+ TypeVar(origin, constr cloneInternal, typeArgs, params) // @M TODO: clone args/params?
+ }
+ }
+
+ /** A type carrying some annotations. Created by the typechecker
+ * when eliminating ``Annotated'' trees (see typedAnnotated).
+ *
+ * @param annotations the list of annotations on the type
+ * @param underlying the type without the annotation
+ * @param selfsym a "self" symbol with type <code>underlying</code>;
+ * only available if -Yself-in-annots is turned on. Can be NoSymbol
+ * if it is not used.
+ */
+ case class AnnotatedType(override val annotations: List[AnnotationInfo],
+ override val underlying: Type,
+ override val selfsym: Symbol)
+ extends RewrappingTypeProxy {
+
+ assert(!annotations.isEmpty)
+
+ override protected def rewrap(tp: Type) = AnnotatedType(annotations, tp, selfsym)
+
+ override def isTrivial: Boolean = isTrivial0
+ private lazy val isTrivial0 = underlying.isTrivial && (annotations forall (_.isTrivial))
+
+ override def safeToString: String = {
+ val attString =
+ if (annotations.isEmpty)
+ ""
+ else
+ annotations.mkString(" @", " @", "")
+
+ underlying + attString
+ }
+
+ /** Add a number of annotations to this type */
+ override def withAnnotations(annots: List[AnnotationInfo]): Type =
+ copy(annots:::this.annotations)
+
+ /** Remove any annotations from this type */
+ override def withoutAnnotations = underlying.withoutAnnotations
+
+ /** Set the self symbol */
+ override def withSelfsym(sym: Symbol) =
+ AnnotatedType(annotations, underlying, sym)
+
+ /** Drop the annotations on the bounds, unless but the low and high
+ * bounds are exactly tp.
+ */
+ override def bounds: TypeBounds = underlying.bounds match {
+ case TypeBounds(_: this.type, _: this.type) => TypeBounds(this, this)
+ case oftp => oftp
+ }
+
+ // ** Replace formal type parameter symbols with actual type arguments. * /
+ override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = {
+ val annotations1 = annotations.map(info => AnnotationInfo(info.atp.instantiateTypeParams(
+ formals, actuals), info.args, info.assocs).setPos(info.pos))
+ val underlying1 = underlying.instantiateTypeParams(formals, actuals)
+ if ((annotations1 eq annotations) && (underlying1 eq underlying)) this
+ else AnnotatedType(annotations1, underlying1, selfsym)
+ }
+
+ /** Return the base type sequence of tp, dropping the annotations, unless the base type sequence of tp
+ * is precisely tp itself. */
+ override def baseTypeSeq: BaseTypeSeq = {
+ val oftp = underlying.baseTypeSeq
+ if ((oftp.length == 1) && (oftp(0) eq underlying))
+ baseTypeSingletonSeq(this)
+ else
+ oftp
+ }
+
+ override def kind = "AnnotatedType"
+ }
+
+ /** A class representing types with a name. When an application uses
+ * named arguments, the named argument types for calling isApplicable
+ * are represented as NamedType.
+ */
+ case class NamedType(name: Name, tp: Type) extends Type {
+ override def safeToString: String = name.toString +": "+ tp
+ }
+
+ /** A class representing an as-yet unevaluated type.
+ */
+ abstract class LazyType extends Type {
+ override def isComplete: Boolean = false
+ override def complete(sym: Symbol)
+ override def safeToString = "<?>"
+ override def kind = "LazyType"
+ }
+
+// Creators ---------------------------------------------------------------
+
+ /** Rebind symbol `sym' to an overriding member in type
+ * `pre'.
+ */
+ private def rebind(pre: Type, sym: Symbol): Symbol = {
+ val owner = sym.owner
+ if (owner.isClass && owner != pre.typeSymbol && !sym.isEffectivelyFinal && !sym.isClass) {
+ //Console.println("rebind "+pre+" "+sym)//DEBUG
+ val rebind = pre.nonPrivateMember(sym.name).suchThat(sym => sym.isType || sym.isStable)
+ if (rebind == NoSymbol) sym
+ else {
+ // Console.println("rebound "+pre+" "+sym+" to "+rebind)//DEBUG
+ rebind
+ }
+ } else sym
+ }
+
+ /** Convert a `super' prefix to a this-type if `sym'
+ * is abstract or final.
+ */
+ private def removeSuper(tp: Type, sym: Symbol): Type = tp match {
+ case SuperType(thistp, _) =>
+ if (sym.isEffectivelyFinal || sym.isDeferred) thistp
+ else tp
+ case _ =>
+ tp
+ }
+
+ /** The canonical creator for single-types */
+ def singleType(pre: Type, sym: Symbol): Type = {
+ if (phase.erasedTypes)
+ sym.tpe.resultType
+ else if (sym.isRootPackage)
+ ThisType(RootClass)
+ else {
+ var sym1 = rebind(pre, sym)
+ val pre1 = removeSuper(pre, sym1)
+ if (pre1 ne pre) sym1 = rebind(pre1, sym1)
+ // why not do the hash-consing in the SingleType.apply()
+ // factory, like the other UniqueTypes?
+ unique(new SingleType(pre1, sym1) with UniqueType)
+ }
+ }
+
+ /** the canonical creator for a refined type with a given scope */
+ def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos : Position): Type = {
+ if (phase.erasedTypes)
+ if (parents.isEmpty) ObjectClass.tpe else parents.head
+ else {
+ val clazz = owner.newRefinementClass(NoPosition)
+ val result = RefinedType(parents, decls, clazz)
+ clazz.setInfo(result)
+ result
+ }
+ }
+
+ /** The canonical creator for a refined type with an initially empty scope.
+ *
+ * @param parents ...
+ * @param owner ...
+ * @return ...
+ */
+ def refinedType(parents: List[Type], owner: Symbol): Type =
+ refinedType(parents, owner, new Scope, owner.pos)
+
+ def copyRefinedType(original: RefinedType, parents: List[Type], decls: Scope) =
+ if ((parents eq original.parents) && (decls eq original.decls)) original
+ else {
+ val owner = if (original.typeSymbol == NoSymbol) NoSymbol else original.typeSymbol.owner
+ val result = refinedType(parents, owner)
+ val syms1 = decls.toList
+ for (sym <- syms1)
+ result.decls.enter(sym.cloneSymbol(result.typeSymbol))
+ val syms2 = result.decls.toList
+ val resultThis = result.typeSymbol.thisType
+ for (sym <- syms2)
+ sym.setInfo(sym.info.substThis(original.typeSymbol, resultThis).substSym(syms1, syms2))
+ result
+ }
+
+ /** The canonical creator for typerefs
+ * todo: see how we can clean this up a bit
+ */
+ def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = {
+ // type alias selections are rebound in TypeMap ("coevolved", actually -- see #3731)
+ // e.g., when type parameters that are referenced by the alias are instantiated in
+ // the prefix. See pos/depmet_rebind_typealias.
+ def rebindTR(pre: Type, sym: Symbol) =
+ if (sym.isAbstractType) rebind(pre, sym) else sym
+
+ val sym1 = rebindTR(pre, sym)
+
+ // we require that object is initialized, thus info.typeParams instead of typeParams.
+ if (sym1.isAliasType && sameLength(sym1.info.typeParams, args)) {
+ if (sym1.lockOK) TypeRef(pre, sym1, args) // don't expand type alias (cycles checked by lockOK)
+ else throw new TypeError("illegal cyclic reference involving " + sym1)
+ }
+ else {
+ val pre1 = removeSuper(pre, sym1)
+ if (pre1 ne pre)
+ typeRef(pre1, rebindTR(pre1, sym1), args)
+ else pre match {
+ case _: CompoundType if sym1.isClass =>
+ // sharpen prefix so that it is maximal and still contains the class.
+ pre.parents.reverse dropWhile (_.member(sym1.name) != sym1) match {
+ case Nil => TypeRef(pre, sym1, args)
+ case parent :: _ => typeRef(parent, sym1, args)
+ }
+ case _ =>
+ TypeRef(pre, sym1, args)
+ }
+ }
+ }
+
+ /** The canonical creator for implicit method types */
+ def JavaMethodType(params: List[Symbol], resultType: Type): JavaMethodType =
+ new JavaMethodType(params, resultType) // don't unique this!
+
+ /** Create a new MethodType of the same class as tp, i.e. keep JavaMethodType */
+ def copyMethodType(tp: Type, params: List[Symbol], restpe: Type): Type = tp match {
+ case _: JavaMethodType => JavaMethodType(params, restpe)
+ case _ => MethodType(params, restpe)
+ }
+
+ /** A creator for intersection type where intersections of a single type are
+ * replaced by the type itself, and repeated parent classes are merged.
+ */
+ def intersectionType(tps: List[Type], owner: Symbol): Type = tps match {
+ case List(tp) =>
+ tp
+ case _ =>
+ refinedType(tps, owner)
+/*
+ def merge(tps: List[Type]): List[Type] = tps match {
+ case tp :: tps1 =>
+ val tps1a = tps1 filter (_.typeSymbol.==(tp.typeSymbol))
+ val tps1b = tps1 filter (_.typeSymbol.!=(tp.typeSymbol))
+ mergePrefixAndArgs(tps1a, -1) match {
+ case Some(tp1) => tp1 :: merge(tps1b)
+ case None => throw new MalformedType(
+ "malformed type: "+refinedType(tps, owner)+" has repeated parent class "+
+ tp.typeSymbol+" with incompatible prefixes or type arguments")
+ }
+ case _ => tps
+ }
+ refinedType(merge(tps), owner)
+*/
+ }
+
+ /** A creator for intersection type where intersections of a single type are
+ * replaced by the type itself. */
+ def intersectionType(tps: List[Type]): Type = tps match {
+ case List(tp) => tp
+ case _ => refinedType(tps, commonOwner(tps))
+ }
+
+ /** A creator for type applications */
+ def appliedType(tycon: Type, args: List[Type]): Type =
+ if (args.isEmpty) tycon //@M! `if (args.isEmpty) tycon' is crucial (otherwise we create new types in phases after typer and then they don't get adapted (??))
+ else tycon match {
+ case TypeRef(pre, sym @ (NothingClass|AnyClass), _) => typeRef(pre, sym, Nil) //@M drop type args to Any/Nothing
+ case TypeRef(pre, sym, _) => typeRef(pre, sym, args)
+ case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args)
+ case ExistentialType(tparams, restpe) => ExistentialType(tparams, appliedType(restpe, args))
+ case st: SingletonType => appliedType(st.widen, args) // @M TODO: what to do? see bug1
+ case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // MO to AM: please check
+ case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args))
+ case tv@TypeVar(_, _) => tv.applyArgs(args)
+ case AnnotatedType(annots, underlying, self) => AnnotatedType(annots, appliedType(underlying, args), self)
+ case ErrorType => tycon
+ case WildcardType => tycon // needed for neg/t0226
+ case _ => abort(debugString(tycon))
+ }
+
+ /** A creator for type parameterizations that strips empty type parameter lists.
+ * Use this factory method to indicate the type has kind * (it's a polymorphic value)
+ * until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty)
+ */
+ def polyType(tparams: List[Symbol], tpe: Type): Type =
+ if (tparams nonEmpty) typeFun(tparams, tpe)
+ else tpe // it's okay to be forgiving here
+
+ /** A creator for anonymous type functions, where the symbol for the type function still needs to be created
+ *
+ * TODO:
+ * type params of anonymous type functions, which currently can only arise from normalising type aliases, are owned by the type alias of which they are the eta-expansion
+ * higher-order subtyping expects eta-expansion of type constructors that arise from a class; here, the type params are owned by that class, but is that the right thing to do?
+ */
+ def typeFunAnon(tps: List[Symbol], body: Type): Type = typeFun(tps, body)
+
+ /** A creator for a type functions, assuming the type parameters tps already have the right owner
+ */
+ def typeFun(tps: List[Symbol], body: Type): Type = PolyType(tps, body)
+
+ /** A creator for existential types. This generates:
+ *
+ * tpe1 where { tparams }
+ *
+ * where `tpe1' is the result of extrapolating `tpe' wrt to `tparams'. Extrapolating means
+ * that type variables in `tparams' occurring in covariant positions are replaced by upper bounds,
+ * (minus any SingletonClass markers),
+ * type variables in `tparams' occurring in contravariant positions are replaced by upper bounds,
+ * provided the resulting type is legal wrt to stability, and does not contain any
+ * type variable in `tparams'.
+ * The abstraction drops all type parameters that are not directly or indirectly
+ * referenced by type `tpe1'.
+ * If there are no remaining type parameters, simply returns result type `tpe'.
+ */
+ def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type =
+ if (tparams.isEmpty) tpe0
+ else {
+ var occurCount = emptySymCount ++ (tparams map (_ -> 0))
+ val tpe = deAlias(tpe0)
+ def countOccs(tp: Type) =
+ for (t <- tp) {
+ t match {
+ case TypeRef(_, sym, _) =>
+ occurCount get sym match {
+ case Some(count) => occurCount += (sym -> (count + 1))
+ case none =>
+ }
+ case _ =>
+ }
+ }
+ countOccs(tpe)
+ for (tparam <- tparams) countOccs(tparam.info)
+
+ val extrapolate = new TypeMap {
+ variance = 1
+ def apply(tp: Type): Type = {
+ val tp1 = mapOver(tp)
+ tp1 match {
+ case TypeRef(pre, sym, args) if (variance != 0) && (occurCount isDefinedAt sym) =>
+ val repl = if (variance == 1) dropSingletonType(tp1.bounds.hi) else tp1.bounds.lo
+ //println("eliminate "+sym+"/"+repl+"/"+occurCount(sym)+"/"+(tparams exists (repl.contains)))//DEBUG
+ if (repl.typeSymbol != NothingClass && repl.typeSymbol != NullClass &&
+ occurCount(sym) == 1 && !(tparams exists (repl.contains)))
+ repl
+ else tp1
+ case _ =>
+ tp1
+ }
+ }
+ override def mapOver(tp: Type): Type = tp match {
+ case SingleType(pre, sym) =>
+ if (sym.isPackageClass) tp // short path
+ else {
+ val pre1 = this(pre)
+ if ((pre1 eq pre) || !pre1.isStable) tp
+ else singleType(pre1, sym)
+ }
+ case _ => super.mapOver(tp)
+ }
+
+ override def mapOver(tree: Tree) =
+ tree match {
+ case tree:Ident if tree.tpe.isStable =>
+ // Do not discard the types of existential ident's.
+ // The symbol of the Ident itself cannot be listed
+ // in the existential's parameters, so the
+ // resulting existential type would be ill-formed.
+ Some(tree)
+
+ case _ =>
+ super.mapOver(tree)
+ }
+ }
+ val tpe1 = extrapolate(tpe)
+ var tparams0 = tparams
+ var tparams1 = tparams0 filter tpe1.contains
+
+ while (tparams1 != tparams0) {
+ tparams0 = tparams1
+ tparams1 = tparams filter { p =>
+ tparams1 exists { p1 => p1 == p || (p1.info contains p) }
+ }
+ }
+ if (tparams1.isEmpty) tpe1
+ else tpe1 match {
+ case ExistentialType(tparams2, tpe2) => ExistentialType(tparams1 ::: tparams2, tpe2)
+ case _ => ExistentialType(tparams1, tpe1)
+ }
+ }
+
+ /** Remove any occurrences of type aliases from this type */
+ object deAlias extends TypeMap {
+ def apply(tp: Type): Type = mapOver {
+ tp match {
+ case TypeRef(pre, sym, args) if sym.isAliasType => tp.normalize
+ case _ => tp
+ }
+ }
+ }
+
+ /** Remove any occurrence of type <singleton> from this type and its parents */
+ object dropSingletonType extends TypeMap {
+ def apply(tp: Type): Type = {
+ tp match {
+ case TypeRef(_, SingletonClass, _) =>
+ AnyClass.tpe
+ case tp1 @ RefinedType(parents, decls) =>
+ var parents1 = parents filter (_.typeSymbol != SingletonClass)
+ if (parents1.isEmpty) parents1 = List(AnyClass.tpe)
+ if (parents1.tail.isEmpty && decls.isEmpty) mapOver(parents1.head)
+ else mapOver(copyRefinedType(tp1, parents1, decls))
+ case tp1 =>
+ mapOver(tp1)
+ }
+ }
+ }
+
+// Hash consing --------------------------------------------------------------
+
+ private val initialUniquesCapacity = 4096
+ private var uniques: util.HashSet[Type] = _
+ private var uniqueRunId = NoRunId
+
+ private def unique[T <: Type](tp: T): T = {
+ incCounter(rawTypeCount)
+ if (uniqueRunId != currentRunId) {
+ uniques = util.HashSet[Type]("uniques", initialUniquesCapacity)
+ uniqueRunId = currentRunId
+ }
+ (uniques findEntryOrUpdate tp).asInstanceOf[T]
+ }
+
+// Helper Classes ---------------------------------------------------------
+
+ /** @PP: Unable to see why these apparently constant types should need vals
+ * in every TypeConstraint, I lifted them out.
+ */
+ private lazy val numericLoBound = IntClass.tpe
+ private lazy val numericHiBound = intersectionType(List(ByteClass.tpe, CharClass.tpe), ScalaPackageClass)
+
+ /** A class expressing upper and lower bounds constraints of type variables,
+ * as well as their instantiations.
+ */
+ class TypeConstraint(lo0: List[Type], hi0: List[Type], numlo0: Type, numhi0: Type) {
+ def this(lo0: List[Type], hi0: List[Type]) = this(lo0, hi0, NoType, NoType)
+ def this() = this(List(), List())
+
+ private var lobounds = lo0
+ private var hibounds = hi0
+ private var numlo = numlo0
+ private var numhi = numhi0
+
+ def loBounds: List[Type] = if (numlo == NoType) lobounds else numlo :: lobounds
+ def hiBounds: List[Type] = if (numhi == NoType) hibounds else numhi :: hibounds
+
+ def addLoBound(tp: Type, isNumericBound: Boolean = false) {
+ if (isNumericBound && isNumericValueType(tp)) {
+ if (numlo == NoType || isNumericSubType(numlo, tp))
+ numlo = tp
+ else if (!isNumericSubType(tp, numlo))
+ numlo = numericLoBound
+ }
+ else lobounds ::= tp
+ }
+
+ def addHiBound(tp: Type, isNumericBound: Boolean = false) {
+ if (isNumericBound && isNumericValueType(tp)) {
+ if (numhi == NoType || isNumericSubType(tp, numhi))
+ numhi = tp
+ else if (!isNumericSubType(numhi, tp))
+ numhi = numericHiBound
+ }
+ else hibounds ::= tp
+ }
+
+ def isWithinBounds(tp: Type): Boolean =
+ lobounds.forall(_ <:< tp) &&
+ hibounds.forall(tp <:< _) &&
+ (numlo == NoType || (numlo weak_<:< tp)) &&
+ (numhi == NoType || (tp weak_<:< numhi))
+
+ var inst: Type = NoType // @M reduce visibility?
+
+ def instValid = (inst ne null) && (inst ne NoType)
+
+ def cloneInternal = {
+ val tc = new TypeConstraint(lobounds, hibounds, numlo, numhi)
+ tc.inst = inst
+ tc
+ }
+
+ override def toString =
+ (loBounds map (_.safeToString)).mkString("[ _>:(", ",", ") ") +
+ (hiBounds map (_.safeToString)).mkString("| _<:(", ",", ") ] _= ") +
+ inst.safeToString
+ }
+
+ /** A prototype for mapping a function over all possible types
+ */
+ abstract class TypeMap extends Function1[Type, Type] {
+ // deferred inherited: def apply(tp: Type): Type
+
+ /** The variance relative to start. If you want variances to be significant, set
+ * variance = 1
+ * at the top of the typemap.
+ */
+ var variance = 0
+
+ /** Should this map drop annotations that are not
+ * type-constraint annotations?
+ */
+ val dropNonConstraintAnnotations = false
+
+ /** Check whether two lists have elements that are eq-equal */
+ def allEq[T <: AnyRef](l1: List[T], l2: List[T]) =
+ (l1 corresponds l2)(_ eq _)
+
+ // #3731: return sym1 for which holds: pre bound sym.name to sym and pre1 now binds sym.name to sym1, conceptually exactly the same symbol as sym
+ // the selection of sym on pre must be updated to the selection of sym1 on pre1,
+ // since sym's info was probably updated by the TypeMap to yield a new symbol sym1 with transformed info
+ // @returns sym1
+ protected def coevolveSym(pre: Type, pre1: Type, sym: Symbol): Symbol =
+ if((pre ne pre1) && sym.isAliasType) // only need to rebind type aliases here, as typeRef already handles abstract types (they are allowed to be rebound more liberally)
+ (pre, pre1) match {
+ case (RefinedType(_, decls), RefinedType(_, decls1)) => // don't look at parents -- it would be an error to override alias types anyway
+ //val sym1 =
+ decls1.lookup(sym.name)
+// assert(decls.lookupAll(sym.name).toList.length == 1)
+// assert(decls1.lookupAll(sym.name).toList.length == 1)
+// assert(sym1.isAliasType)
+// println("coevolved "+ sym +" : "+ sym.info +" to "+ sym1 +" : "+ sym1.info +" with "+ pre +" -> "+ pre1)
+// sym1
+ case _ => // TODO: is there another way a typeref's symbol can refer to a symbol defined in its pre?
+// val sym1 = pre1.nonPrivateMember(sym.name).suchThat(sym => sym.isAliasType)
+// println("??coevolve "+ sym +" : "+ sym.info +" to "+ sym1 +" : "+ sym1.info +" with "+ pre +" -> "+ pre1)
+ sym
+ }
+ else sym
+
+ /** Map this function over given type */
+ def mapOver(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) =>
+ val pre1 = this(pre)
+ //val args1 = args mapConserve this(_)
+ val args1 = if (args.isEmpty) args
+ else {
+ val tparams = sym.typeParams
+ if (tparams.isEmpty) args
+ else mapOverArgs(args, tparams)
+ }
+ if ((pre1 eq pre) && (args1 eq args)) tp
+ else typeRef(pre1, coevolveSym(pre, pre1, sym), args1)
+ case ThisType(_) => tp
+ case SingleType(pre, sym) =>
+ if (sym.isPackageClass) tp // short path
+ else {
+ val pre1 = this(pre)
+ if (pre1 eq pre) tp
+ else singleType(pre1, sym)
+ }
+ case MethodType(params, result) =>
+ variance = -variance
+ val params1 = mapOver(params)
+ variance = -variance
+ val result1 = this(result)
+ if ((params1 eq params) && (result1 eq result)) tp
+ // for new dependent types: result1.substSym(params, params1)?
+ else copyMethodType(tp, params1, result1.substSym(params, params1))
+ case PolyType(tparams, result) =>
+ variance = -variance
+ val tparams1 = mapOver(tparams)
+ variance = -variance
+ var result1 = this(result)
+ if ((tparams1 eq tparams) && (result1 eq result)) tp
+ else PolyType(tparams1, result1.substSym(tparams, tparams1))
+ case NullaryMethodType(result) =>
+ val result1 = this(result)
+ if (result1 eq result) tp
+ else NullaryMethodType(result1)
+ case ConstantType(_) => tp
+ case SuperType(thistp, supertp) =>
+ val thistp1 = this(thistp)
+ val supertp1 = this(supertp)
+ if ((thistp1 eq thistp) && (supertp1 eq supertp)) tp
+ else SuperType(thistp1, supertp1)
+ case TypeBounds(lo, hi) =>
+ variance = -variance
+ val lo1 = this(lo)
+ variance = -variance
+ val hi1 = this(hi)
+ if ((lo1 eq lo) && (hi1 eq hi)) tp
+ else TypeBounds(lo1, hi1)
+ case BoundedWildcardType(bounds) =>
+ val bounds1 = this(bounds)
+ if (bounds1 eq bounds) tp
+ else BoundedWildcardType(bounds1.asInstanceOf[TypeBounds])
+ case rtp @ RefinedType(parents, decls) =>
+ val parents1 = parents mapConserve (this)
+ val decls1 = mapOver(decls)
+ //if ((parents1 eq parents) && (decls1 eq decls)) tp
+ //else refinementOfClass(tp.typeSymbol, parents1, decls1)
+ copyRefinedType(rtp, parents1, decls1)
+ case ExistentialType(tparams, result) =>
+ val tparams1 = mapOver(tparams)
+ var result1 = this(result)
+ if ((tparams1 eq tparams) && (result1 eq result)) tp
+ else ExistentialType(tparams1, result1.substSym(tparams, tparams1))
+ case OverloadedType(pre, alts) =>
+ val pre1 = if (pre.isInstanceOf[ClassInfoType]) pre else this(pre)
+ if (pre1 eq pre) tp
+ else OverloadedType(pre1, alts)
+ case AntiPolyType(pre, args) =>
+ val pre1 = this(pre)
+ val args1 = args mapConserve (this)
+ if ((pre1 eq pre) && (args1 eq args)) tp
+ else AntiPolyType(pre1, args1)
+ case tv@TypeVar(_, constr) =>
+ if (constr.instValid) this(constr.inst)
+ else tv.applyArgs(mapOverArgs(tv.typeArgs, tv.params)) //@M !args.isEmpty implies !typeParams.isEmpty
+ case NotNullType(tp) =>
+ val tp1 = this(tp)
+ if (tp1 eq tp) tp
+ else NotNullType(tp1)
+ case AnnotatedType(annots, atp, selfsym) =>
+ val annots1 = mapOverAnnotations(annots)
+ val atp1 = this(atp)
+ if ((annots1 eq annots) && (atp1 eq atp)) tp
+ else if (annots1.isEmpty) atp1
+ else AnnotatedType(annots1, atp1, selfsym)
+/*
+ case ErrorType => tp
+ case WildcardType => tp
+ case NoType => tp
+ case NoPrefix => tp
+*/
+ case _ =>
+ tp
+ // throw new Error("mapOver inapplicable for " + tp);
+ }
+
+ def mapOverArgs(args: List[Type], tparams: List[Symbol]): List[Type] =
+ map2Conserve(args, tparams) { (arg, tparam) =>
+ val v = variance
+ if (tparam.isContravariant) variance = -variance
+ else if (!tparam.isCovariant) variance = 0
+ val arg1 = this(arg)
+ variance = v
+ arg1
+ }
+
+ /** Map this function over given scope */
+ def mapOver(scope: Scope): Scope = {
+ val elems = scope.toList
+ val elems1 = mapOver(elems)
+ if (elems1 eq elems) scope
+ else new Scope(elems1)
+ }
+
+ /** Map this function over given list of symbols */
+ def mapOver(origSyms: List[Symbol]): List[Symbol] = {
+ val change = origSyms exists { sym =>
+ val v = variance
+ if (sym.isAliasType) variance = 0
+ val result = this(sym.info)
+ variance = v
+ result ne sym.info
+ }
+ if (!change) origSyms // fast path in case nothing changes due to map
+ else { // map is not the identity --> do cloning properly
+ val clonedSyms = origSyms map (_.cloneSymbol)
+ val clonedInfos = clonedSyms map (_.info.substSym(origSyms, clonedSyms))
+ val transformedInfos = clonedInfos mapConserve (this)
+ (clonedSyms, transformedInfos).zipped map (_ setInfo _)
+
+ clonedSyms
+ }
+ }
+
+
+ def mapOverAnnotations(annots: List[AnnotationInfo])
+ : List[AnnotationInfo] = {
+ val newAnnots = annots.flatMap(mapOver(_))
+ if (allEq(newAnnots, annots))
+ annots
+ else
+ newAnnots
+ }
+
+ def mapOver(annot: AnnotationInfo): Option[AnnotationInfo] = {
+ val AnnotationInfo(atp, args, assocs) = annot
+
+ if (dropNonConstraintAnnotations &&
+ !(atp.typeSymbol isNonBottomSubClass TypeConstraintClass))
+ return None
+
+ val atp1 = mapOver(atp)
+ val args1 = mapOverAnnotArgs(args)
+ // there is no need to rewrite assocs, as they are constants
+
+ if ((args eq args1) && (atp eq atp1))
+ Some(annot)
+ else if (sameLength(args1, args))
+ Some(AnnotationInfo(atp1, args1, assocs).setPos(annot.pos))
+ else
+ None
+ }
+
+ /** Map over a set of annotation arguments. If any
+ * of the arguments cannot be mapped, then return Nil. */
+ def mapOverAnnotArgs(args: List[Tree]): List[Tree] = {
+ val args1 = args flatMap (x => mapOver(x))
+ if (!sameLength(args1, args))
+ Nil
+ else if (allEq(args, args1))
+ args
+ else
+ args1
+ }
+
+ def mapOver(tree: Tree): Option[Tree] =
+ Some(mapOver(tree, ()=>return None))
+
+ /** Map a tree that is part of an annotation argument.
+ * If the tree cannot be mapped, then invoke giveup().
+ * The default is to transform the tree with
+ * TypeMapTransformer.
+ */
+ def mapOver(tree: Tree, giveup: ()=>Nothing): Tree =
+ (new TypeMapTransformer).transform(tree)
+
+ /** This transformer leaves the tree alone except to remap
+ * its types. */
+ class TypeMapTransformer extends Transformer {
+ override def transform(tree: Tree) = {
+ val tree1 = super.transform(tree)
+ val tpe1 = TypeMap.this(tree1.tpe)
+ if ((tree eq tree1) && (tree.tpe eq tpe1))
+ tree
+ else
+ tree1.shallowDuplicate.setType(tpe1)
+ }
+ }
+ }
+
+ /** A type map that always returns the input type unchanged */
+ object IdentityTypeMap extends TypeMap {
+ def apply(tp: Type) = tp
+ }
+
+ abstract class TypeTraverser extends TypeMap {
+ def traverse(tp: Type): Unit
+ def apply(tp: Type): Type = { traverse(tp); tp }
+ }
+
+ abstract class TypeCollector[T](initial: T) extends TypeTraverser {
+ var result: T = _
+ def collect(tp: Type) = {
+ result = initial
+ traverse(tp)
+ result
+ }
+ }
+
+ private val emptySymMap = immutable.Map[Symbol, Symbol]()
+ private val emptySymCount = immutable.Map[Symbol, Int]()
+
+ def typeParamsToExistentials(clazz: Symbol, tparams: List[Symbol]): List[Symbol] = {
+ val eparams = for ((tparam, i) <- tparams.zipWithIndex) yield {
+ clazz.newExistential(clazz.pos, newTypeName("?"+i)).setInfo(tparam.info.bounds)
+ }
+ for (tparam <- eparams) tparam setInfo tparam.info.substSym(tparams, eparams)
+ eparams
+ }
+
+ // note: it's important to write the two tests in this order,
+ // as only typeParams forces the classfile to be read. See #400
+ private def isRawIfWithoutArgs(sym: Symbol) =
+ sym.isClass && sym.typeParams.nonEmpty && sym.isJavaDefined
+
+ def isRaw(sym: Symbol, args: List[Type]) =
+ !phase.erasedTypes && isRawIfWithoutArgs(sym) && args.isEmpty
+
+ /** Is type tp a ``raw type''? */
+ def isRawType(tp: Type) = tp match {
+ case TypeRef(_, sym, args) => isRaw(sym, args)
+ case _ => false
+ }
+
+ /** The raw to existential map converts a ``raw type'' to an existential type.
+ * It is necessary because we might have read a raw type of a
+ * parameterized Java class from a class file. At the time we read the type
+ * the corresponding class file might still not be read, so we do not
+ * know what the type parameters of the type are. Therefore
+ * the conversion of raw types to existential types might not have taken place
+ * in ClassFileparser.sigToType (where it is usually done)
+ */
+ object rawToExistential extends TypeMap {
+ private var expanded = immutable.Set[Symbol]()
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, List()) if isRawIfWithoutArgs(sym) =>
+ if (expanded contains sym) AnyRefClass.tpe
+ else try {
+ expanded += sym
+ val eparams = mapOver(typeParamsToExistentials(sym, sym.typeParams))
+ existentialAbstraction(eparams, typeRef(apply(pre), sym, eparams map (_.tpe)))
+ } finally {
+ expanded -= sym
+ }
+ case ExistentialType(_, _) => // stop to avoid infinite expansions
+ tp
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ def singletonBounds(hi: Type) = {
+ TypeBounds.upper(intersectionType(List(hi, SingletonClass.tpe)))
+ }
+
+ /** A map to compute the asSeenFrom method */
+ class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap {
+ override val dropNonConstraintAnnotations = true
+
+ var capturedParams: List[Symbol] = List()
+
+ override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
+ object annotationArgRewriter extends TypeMapTransformer {
+ /** Rewrite `This` trees in annotation argument trees */
+ def rewriteThis(tree: Tree): Tree =
+ tree match {
+ case This(_)
+ if (tree.symbol isNonBottomSubClass clazz) &&
+ (pre.widen.typeSymbol isNonBottomSubClass tree.symbol) =>
+ if (pre.isStable) { // XXX why is this in this method? pull it out and guard the call `annotationArgRewriter.transform(tree)`?
+ val termSym =
+ pre.typeSymbol.owner.newValue(
+ pre.typeSymbol.pos,
+ pre.typeSymbol.name.toTermName).setInfo(pre) // what symbol should really be used?
+ gen.mkAttributedQualifier(pre, termSym)
+ } else
+ giveup()
+
+ case tree => tree
+ }
+
+ override def transform(tree: Tree): Tree = {
+ val tree1 = rewriteThis(super.transform(tree))
+ tree1
+ }
+ }
+
+ annotationArgRewriter.transform(tree)
+ }
+
+ var capturedPre = emptySymMap
+
+ def stabilize(pre: Type, clazz: Symbol): Type =
+ capturedPre.getOrElse(clazz, {
+ val qvar = clazz freshExistential ".type" setInfo singletonBounds(pre)
+ capturedPre += (clazz -> qvar)
+ capturedParams = qvar :: capturedParams
+ qvar
+ }).tpe
+
+ /** Return pre.baseType(clazz), or if that's NoType and clazz is a refinement, pre itself.
+ * See bug397.scala for an example where the second alternative is needed.
+ * The problem is that when forming the base type sequence of an abstract type,
+ * any refinements in the base type list might be regenerated, and thus acquire
+ * new class symbols. However, since refinements always have non-interesting prefixes
+ * it looks OK to me to just take the prefix directly. */
+ def base(pre: Type, clazz: Symbol) = {
+ val b = pre.baseType(clazz)
+ if (b == NoType && clazz.isRefinementClass) pre
+ else b
+ }
+
+ def apply(tp: Type): Type =
+ if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) tp
+ else tp match {
+ case ThisType(sym) =>
+ def toPrefix(pre: Type, clazz: Symbol): Type =
+ if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) tp
+ else if ((sym isNonBottomSubClass clazz) &&
+ (pre.widen.typeSymbol isNonBottomSubClass sym)) {
+ val pre1 = pre match {
+ case SuperType(thistp, _) => thistp
+ case _ => pre
+ }
+ if (!(pre1.isStable ||
+ pre1.typeSymbol.isPackageClass ||
+ pre1.typeSymbol.isModuleClass && pre1.typeSymbol.isStatic)) {
+ stabilize(pre1, sym)
+ } else {
+ pre1
+ }
+ } else {
+ toPrefix(base(pre, clazz).prefix, clazz.owner);
+ }
+ toPrefix(pre, clazz)
+ case SingleType(pre, sym) =>
+ if (sym.isPackageClass) tp // short path
+ else {
+ val pre1 = this(pre)
+ if (pre1 eq pre) tp
+ else if (pre1.isStable) singleType(pre1, sym)
+ else pre1.memberType(sym).resultType //todo: this should be rolled into existential abstraction
+ }
+ // AM: Martin, is this description accurate?
+ // walk the owner chain of `clazz` (the original argument to asSeenFrom) until we find the type param's owner (while rewriting pre as we crawl up the owner chain)
+ // once we're at the owner, extract the information that pre encodes about the type param,
+ // by minimally subsuming pre to the type instance of the class that owns the type param,
+ // the type we're looking for is the type instance's type argument at the position corresponding to the type parameter
+ // optimisation: skip this type parameter if it's not owned by a class, as those params are not influenced by the prefix through which they are seen
+ // (concretely: type params of anonymous type functions, which currently can only arise from normalising type aliases, are owned by the type alias of which they are the eta-expansion)
+ // (skolems also aren't affected: they are ruled out by the isTypeParameter check)
+ case TypeRef(prefix, sym, args) if (sym.isTypeParameter && sym.owner.isClass) =>
+ def toInstance(pre: Type, clazz: Symbol): Type =
+ if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) mapOver(tp)
+ //@M! see test pos/tcpoly_return_overriding.scala why mapOver is necessary
+ else {
+ def throwError = abort("" + tp + sym.locationString + " cannot be instantiated from " + pre.widen)
+
+ def instParam(ps: List[Symbol], as: List[Type]): Type =
+ if (ps.isEmpty) throwError
+ else if (sym eq ps.head)
+ // @M! don't just replace the whole thing, might be followed by type application
+ appliedType(as.head, args mapConserve (this)) // @M: was as.head
+ else instParam(ps.tail, as.tail);
+ val symclazz = sym.owner
+ if (symclazz == clazz && !pre.isInstanceOf[TypeVar] && (pre.widen.typeSymbol isNonBottomSubClass symclazz)) {
+ // have to deconst because it may be a Class[T].
+ pre.baseType(symclazz).deconst match {
+ case TypeRef(_, basesym, baseargs) =>
+ //Console.println("instantiating " + sym + " from " + basesym + " with " + basesym.typeParams + " and " + baseargs+", pre = "+pre+", symclazz = "+symclazz);//DEBUG
+ if (sameLength(basesym.typeParams, baseargs)) {
+ instParam(basesym.typeParams, baseargs)
+ } else {
+ throw new TypeError(
+ "something is wrong (wrong class file?): "+basesym+
+ " with type parameters "+
+ basesym.typeParams.map(_.name).mkString("[",",","]")+
+ " gets applied to arguments "+baseargs.mkString("[",",","]")+", phase = "+phase)
+ }
+ case ExistentialType(tparams, qtpe) =>
+ capturedParams = capturedParams union tparams
+ toInstance(qtpe, clazz)
+ case _ =>
+ throwError
+ }
+ } else toInstance(base(pre, clazz).prefix, clazz.owner)
+ }
+ toInstance(pre, clazz)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ /** A base class to compute all substitutions */
+ abstract class SubstMap[T](from: List[Symbol], to: List[T]) extends TypeMap {
+ val fromContains = from.toSet // avoiding repeatedly traversing from
+ assert(sameLength(from, to), "Unsound substitution from "+ from +" to "+ to)
+
+ /** Are `sym' and `sym1' the same.
+ * Can be tuned by subclasses.
+ */
+ protected def matches(sym: Symbol, sym1: Symbol): Boolean = sym eq sym1
+
+ /** Map target to type, can be tuned by subclasses */
+ protected def toType(fromtp: Type, tp: T): Type
+
+ def subst(tp: Type, sym: Symbol, from: List[Symbol], to: List[T]): Type =
+ if (from.isEmpty) tp
+ // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(tp, from))
+ else if (matches(from.head, sym)) toType(tp, to.head)
+ else subst(tp, sym, from.tail, to.tail)
+
+ protected def renameBoundSyms(tp: Type): Type = tp match {
+ case MethodType(ps, restp) =>
+ val ps1 = cloneSymbols(ps)
+ copyMethodType(tp, ps1, renameBoundSyms(restp.substSym(ps, ps1)))
+ case PolyType(bs, restp) =>
+ val bs1 = cloneSymbols(bs)
+ PolyType(bs1, renameBoundSyms(restp.substSym(bs, bs1)))
+ case ExistentialType(bs, restp) =>
+ val bs1 = cloneSymbols(bs)
+ ExistentialType(bs1, restp.substSym(bs, bs1))
+ case _ =>
+ tp
+ }
+
+ def apply(tp0: Type): Type = if (from.isEmpty) tp0 else {
+ val boundSyms = tp0.boundSyms
+ val tp1 = if (boundSyms exists fromContains) renameBoundSyms(tp0) else tp0
+ val tp = mapOver(tp1)
+
+ tp match {
+ // @M
+ // 1) arguments must also be substituted (even when the "head" of the
+ // applied type has already been substituted)
+ // example: (subst RBound[RT] from [type RT,type RBound] to
+ // [type RT&,type RBound&]) = RBound&[RT&]
+ // 2) avoid loops (which occur because alpha-conversion is
+ // not performed properly imo)
+ // e.g. if in class Iterable[a] there is a new Iterable[(a,b)],
+ // we must replace the a in Iterable[a] by (a,b)
+ // (must not recurse --> loops)
+ // 3) replacing m by List in m[Int] should yield List[Int], not just List
+ case TypeRef(NoPrefix, sym, args) =>
+ appliedType(subst(tp, sym, from, to), args) // if args.isEmpty, appliedType is the identity
+ case SingleType(NoPrefix, sym) =>
+ subst(tp, sym, from, to)
+ case _ =>
+ tp
+ }
+ }
+ }
+
+ /** A map to implement the `substSym' method. */
+ class SubstSymMap(from: List[Symbol], to: List[Symbol]) extends SubstMap(from, to) {
+ protected def toType(fromtp: Type, sym: Symbol) = fromtp match {
+ case TypeRef(pre, _, args) => typeRef(pre, sym, args)
+ case SingleType(pre, _) => singleType(pre, sym)
+ }
+ override def apply(tp: Type): Type = if (from.isEmpty) tp else {
+ def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol =
+ if (from.isEmpty) sym
+ // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(sym, from))
+ else if (matches(from.head, sym)) to.head
+ else subst(sym, from.tail, to.tail)
+ tp match {
+ case TypeRef(pre, sym, args) if pre ne NoPrefix =>
+ val newSym = subst(sym, from, to)
+ // assert(newSym.typeParams.length == sym.typeParams.length, "typars mismatch in SubstSymMap: "+(sym, sym.typeParams, newSym, newSym.typeParams))
+ mapOver(typeRef(pre, newSym, args)) // mapOver takes care of subst'ing in args
+ case SingleType(pre, sym) if pre ne NoPrefix =>
+ mapOver(singleType(pre, subst(sym, from, to)))
+ case _ =>
+ super.apply(tp)
+ }
+ }
+
+
+ override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
+ object trans extends TypeMapTransformer {
+
+ def termMapsTo(sym: Symbol) =
+ if (fromContains(sym))
+ Some(to(from.indexOf(sym)))
+ else
+ None
+
+ override def transform(tree: Tree) =
+ tree match {
+ case tree@Ident(_) =>
+ termMapsTo(tree.symbol) match {
+ case Some(tosym) =>
+ if (tosym.info.bounds.hi.typeSymbol isSubClass SingletonClass) {
+ Ident(tosym.existentialToString)
+ .setSymbol(tosym)
+ .setPos(tosym.pos)
+ .setType(dropSingletonType(tosym.info.bounds.hi))
+ } else {
+ giveup()
+ }
+ case none => super.transform(tree)
+ }
+ case tree => super.transform(tree)
+ }
+ }
+ trans.transform(tree)
+ }
+ }
+
+ /** A map to implement the `subst' method. */
+ class SubstTypeMap(from: List[Symbol], to: List[Type])
+ extends SubstMap(from, to) {
+ protected def toType(fromtp: Type, tp: Type) = tp
+
+ override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
+ object trans extends TypeMapTransformer {
+ override def transform(tree: Tree) =
+ tree match {
+ case Ident(name) if fromContains(tree.symbol) =>
+ val totpe = to(from.indexOf(tree.symbol))
+ if (!totpe.isStable) giveup()
+ else Ident(name).setPos(tree.pos).setSymbol(tree.symbol).setType(totpe)
+
+ case _ => super.transform(tree)
+ }
+ }
+ trans.transform(tree)
+ }
+
+ }
+
+ /** A map to implement the `substThis' method. */
+ class SubstThisMap(from: Symbol, to: Type) extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case ThisType(sym) if (sym == from) => to
+ case _ => mapOver(tp)
+ }
+ }
+
+ class SubstSuperMap(from: Type, to: Type) extends TypeMap {
+ def apply(tp: Type): Type = if (tp eq from) to else mapOver(tp)
+ }
+
+ class SubstWildcardMap(from: List[Symbol]) extends TypeMap {
+ def apply(tp: Type): Type = try {
+ tp match {
+ case TypeRef(_, sym, _) if from contains sym =>
+ BoundedWildcardType(sym.info.bounds)
+ case _ =>
+ mapOver(tp)
+ }
+ } catch {
+ case ex: MalformedType =>
+ WildcardType
+ }
+ }
+
+// dependent method types
+ object IsDependentCollector extends TypeCollector(false) {
+ def traverse(tp: Type) {
+ if(tp isImmediatelyDependent) result = true
+ else if (!result) mapOver(tp)
+ }
+ }
+
+ object ApproximateDependentMap extends TypeMap {
+ def apply(tp: Type): Type =
+ if(tp isImmediatelyDependent) WildcardType
+ else mapOver(tp)
+ }
+
+ class InstantiateDependentMap(params: List[Symbol], actuals: List[Type]) extends TypeMap {
+ private val actualsIndexed = actuals.toIndexedSeq
+ override val dropNonConstraintAnnotations = true
+
+ object ParamWithActual {
+ def unapply(sym: Symbol): Option[Type] = {
+ val pid = params indexOf sym
+ if(pid != -1) Some(actualsIndexed(pid)) else None
+ }
+ }
+
+ def apply(tp: Type): Type =
+ mapOver(tp) match {
+ case SingleType(NoPrefix, ParamWithActual(arg)) if arg.isStable => arg // unsound to replace args by unstable actual #3873
+ // (soundly) expand type alias selections on implicit arguments, see depmet_implicit_oopsla* test cases -- typically, `param.isImplicit`
+ case tp1@TypeRef(SingleType(NoPrefix, ParamWithActual(arg)), sym, targs) =>
+ val res = typeRef(arg, sym, targs)
+ if(res.typeSymbolDirect isAliasType) res.dealias
+ else tp1
+ case tp1 => tp1 // don't return the original `tp`, which may be different from `tp1`, due to `dropNonConstraintAnnotations`
+ }
+
+ def existentialsNeeded: List[Symbol] = existSyms.filter(_ ne null).toList
+
+ private val existSyms: Array[Symbol] = new Array(actualsIndexed.size)
+ private def haveExistential(i: Int) = {assert((i >= 0) && (i <= actualsIndexed.size)); existSyms(i) ne null}
+
+ /* Return the type symbol for referencing a parameter inside the existential quantifier.
+ * (Only needed if the actual is unstable.)
+ */
+ def existSymFor(actualIdx: Int) =
+ if (haveExistential(actualIdx)) existSyms(actualIdx)
+ else {
+ val oldSym = params(actualIdx)
+ val symowner = oldSym.owner
+ val bound = singletonBounds(actualsIndexed(actualIdx))
+
+ val sym = symowner.newExistential(oldSym.pos, newTypeName(oldSym.name + ".type"))
+ sym.setInfo(bound)
+ sym.setFlag(oldSym.flags)
+
+ existSyms(actualIdx) = sym
+ sym
+ }
+
+ //AM propagate more info to annotations -- this seems a bit ad-hoc... (based on code by spoon)
+ override def mapOver(arg: Tree, giveup: ()=>Nothing): Tree = {
+ object treeTrans extends Transformer {
+ override def transform(tree: Tree): Tree = {
+ tree match {
+ case RefParamAt(pid) =>
+ // TODO: this should be simplified; in the stable case, one can probably
+ // just use an Ident to the tree.symbol. Why an existential in the non-stable case?
+ val actual = actualsIndexed(pid)
+ if (actual.isStable && actual.typeSymbol != NothingClass) {
+ gen.mkAttributedQualifier(actualsIndexed(pid), tree.symbol)
+ } else {
+ val sym = existSymFor(pid)
+ (Ident(sym.name)
+ copyAttrs tree
+ setType typeRef(NoPrefix, sym, Nil))
+ }
+ case _ => super.transform(tree)
+ }
+ }
+ object RefParamAt {
+ def unapply(tree: Tree): Option[Int] = tree match {
+ case Ident(_) => Some(params indexOf tree.symbol) filterNot (_ == -1)
+ case _ => None
+ }
+ }
+ }
+
+ treeTrans.transform(arg)
+ }
+ }
+
+
+ object StripAnnotationsMap extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case AnnotatedType(_, atp, _) =>
+ mapOver(atp)
+ case tp =>
+ mapOver(tp)
+ }
+ }
+
+ /** A map to convert every occurrence of a wildcard type to a fresh
+ * type variable */
+ object wildcardToTypeVarMap extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case WildcardType =>
+ TypeVar(tp, new TypeConstraint)
+ case BoundedWildcardType(bounds) =>
+ TypeVar(tp, new TypeConstraint(List(bounds.lo), List(bounds.hi)))
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ /** A map to convert every occurrence of a type variable to a
+ wildcard type */
+ object typeVarToOriginMap extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeVar(origin, _) => origin
+ case _ => mapOver(tp)
+ }
+ }
+
+ /** A map to implement the `contains' method */
+ class ContainsCollector(sym: Symbol) extends TypeCollector(false) {
+ def traverse(tp: Type) {
+ if (!result) {
+ tp.normalize match {
+ case TypeRef(_, sym1, _) if (sym == sym1) => result = true
+ case SingleType(_, sym1) if (sym == sym1) => result = true
+ case _ => mapOver(tp)
+ }
+ }
+ }
+
+ override def mapOver(arg: Tree) = {
+ for (t <- arg) {
+ traverse(t.tpe)
+ if (t.symbol == sym)
+ result = true
+ }
+ Some(arg)
+ }
+ }
+
+ /** A map to implement the `contains' method */
+ class ContainsTypeCollector(t: Type) extends TypeCollector(false) {
+ def traverse(tp: Type) {
+ if (!result) {
+ if (tp eq t) result = true
+ else mapOver(tp)
+ }
+ }
+ override def mapOver(arg: Tree) = {
+ for (t <- arg) {
+ traverse(t.tpe)
+ }
+ Some(arg)
+ }
+ }
+
+ /** A map to implement the `filter' method */
+ class FilterTypeCollector(p: Type => Boolean) extends TypeCollector(new ListBuffer[Type]) {
+ def traverse(tp: Type) {
+ if (p(tp)) result += tp
+ mapOver(tp)
+ }
+ }
+
+ class ForEachTypeTraverser(f: Type => Unit) extends TypeTraverser {
+ def traverse(tp: Type) {
+ f(tp)
+ mapOver(tp)
+ }
+ }
+
+ /** A map to implement the `filter' method */
+ class FindTypeCollector(p: Type => Boolean) extends TypeCollector[Option[Type]](None) {
+ def traverse(tp: Type) {
+ if (result.isEmpty) {
+ if (p(tp)) result = Some(tp)
+ mapOver(tp)
+ }
+ }
+ }
+
+ /** A map to implement the `contains' method */
+ object ErroneousCollector extends TypeCollector(false) {
+ def traverse(tp: Type) {
+ if (!result) {
+ result = tp.isError
+ mapOver(tp)
+ }
+ }
+ }
+
+ /** A map to compute the most deeply nested owner that contains all the symbols
+ * of thistype or prefixless typerefs/singletype occurrences in given type.
+ */
+ object commonOwnerMap extends TypeMap {
+ var result: Symbol = _
+ def init() = { result = NoSymbol }
+ def apply(tp: Type): Type = {
+ assert(tp ne null)
+ tp.normalize match {
+ case ThisType(sym) =>
+ register(sym)
+ case TypeRef(NoPrefix, sym, args) =>
+ register(sym.owner); args foreach apply
+ case SingleType(NoPrefix, sym) =>
+ register(sym.owner)
+ case _ =>
+ mapOver(tp)
+ }
+ tp
+ }
+ private def register(sym: Symbol) {
+ while (result != NoSymbol && sym != result && !(sym isNestedIn result))
+ result = result.owner;
+ }
+ }
+
+ class MissingAliasControl extends ControlThrowable
+ val missingAliasException = new MissingAliasControl
+ class MissingTypeControl extends ControlThrowable
+
+ object adaptToNewRunMap extends TypeMap {
+ private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
+ if (phase.flatClasses) {
+ sym
+ } else if (sym.isModuleClass) {
+ adaptToNewRun(pre, sym.sourceModule).moduleClass
+ } else if ((pre eq NoPrefix) || (pre eq NoType) || sym.isPackageClass) {
+ sym
+ } else {
+ var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true)
+ if (rebind0 == NoSymbol) {
+ if (sym.isAliasType) throw missingAliasException
+ if (settings.debug.value) println(pre+"."+sym+" does no longer exist, phase = "+phase)
+ throw new MissingTypeControl // For build manager and presentation compiler purposes
+ //assert(false, pre+"."+sym+" does no longer exist, phase = "+phase)
+ }
+ /** The two symbols have the same fully qualified name */
+ def corresponds(sym1: Symbol, sym2: Symbol): Boolean =
+ sym1.name == sym2.name && (sym1.isPackageClass || corresponds(sym1.owner, sym2.owner))
+ if (!corresponds(sym.owner, rebind0.owner)) {
+ if (settings.debug.value)
+ log("ADAPT1 pre = "+pre+", sym = "+sym+sym.locationString+", rebind = "+rebind0+rebind0.locationString)
+ val bcs = pre.baseClasses.dropWhile(bc => !corresponds(bc, sym.owner));
+ if (bcs.isEmpty)
+ assert(pre.typeSymbol.isRefinementClass, pre) // if pre is a refinementclass it might be a structural type => OK to leave it in.
+ else
+ rebind0 = pre.baseType(bcs.head).member(sym.name)
+ if (settings.debug.value) log(
+ "ADAPT2 pre = " + pre +
+ ", bcs.head = " + bcs.head +
+ ", sym = " + sym+sym.locationString +
+ ", rebind = " + rebind0 + (
+ if (rebind0 == NoSymbol) ""
+ else rebind0.locationString
+ )
+ )
+ }
+ val rebind = rebind0.suchThat(sym => sym.isType || sym.isStable)
+ if (rebind == NoSymbol) {
+ if (settings.debug.value) log("" + phase + " " +phase.flatClasses+sym.owner+sym.name+" "+sym.isType)
+ throw new MalformedType(pre, sym.nameString)
+ }
+ rebind
+ }
+ }
+ def apply(tp: Type): Type = tp match {
+ case ThisType(sym) =>
+ try {
+ val sym1 = adaptToNewRun(sym.owner.thisType, sym)
+ if (sym1 == sym) tp else ThisType(sym1)
+ } catch {
+ case ex: MissingTypeControl =>
+ tp
+ }
+ case SingleType(pre, sym) =>
+ if (sym.isPackage) tp
+ else {
+ val pre1 = this(pre)
+ val sym1 = adaptToNewRun(pre1, sym)
+ if ((pre1 eq pre) && (sym1 eq sym)) tp
+ else singleType(pre1, sym1)
+ }
+ case TypeRef(pre, sym, args) =>
+ if (sym.isPackageClass) tp
+ else {
+ val pre1 = this(pre)
+ val args1 = args mapConserve (this)
+ try {
+ val sym1 = adaptToNewRun(pre1, sym)
+ if ((pre1 eq pre) && (sym1 eq sym) && (args1 eq args)/* && sym.isExternal*/) tp
+ else typeRef(pre1, sym1, args1)
+ } catch {
+ case ex: MissingAliasControl =>
+ apply(tp.dealias)
+ case _: MissingTypeControl =>
+ tp
+ }
+ }
+ case MethodType(params, restp) =>
+ val restp1 = this(restp)
+ if (restp1 eq restp) tp
+ else copyMethodType(tp, params, restp1)
+ case NullaryMethodType(restp) =>
+ val restp1 = this(restp)
+ if (restp1 eq restp) tp
+ else NullaryMethodType(restp1)
+ case PolyType(tparams, restp) =>
+ val restp1 = this(restp)
+ if (restp1 eq restp) tp
+ else PolyType(tparams, restp1)
+
+ // Lukas: we need to check (together) whether we should also include parameter types
+ // of PolyType and MethodType in adaptToNewRun
+
+ case ClassInfoType(parents, decls, clazz) =>
+ if (clazz.isPackageClass) tp
+ else {
+ val parents1 = parents mapConserve (this)
+ if (parents1 eq parents) tp
+ else ClassInfoType(parents1, decls, clazz)
+ }
+ case RefinedType(parents, decls) =>
+ val parents1 = parents mapConserve (this)
+ if (parents1 eq parents) tp
+ else refinedType(parents1, tp.typeSymbol.owner, decls, tp.typeSymbol.owner.pos)
+ case SuperType(_, _) => mapOver(tp)
+ case TypeBounds(_, _) => mapOver(tp)
+ case TypeVar(_, _) => mapOver(tp)
+ case AnnotatedType(_,_,_) => mapOver(tp)
+ case NotNullType(_) => mapOver(tp)
+ case ExistentialType(_, _) => mapOver(tp)
+ case _ => tp
+ }
+ }
+
+ class SubTypePair(val tp1: Type, val tp2: Type) {
+ override def hashCode = tp1.hashCode * 41 + tp2.hashCode
+ override def equals(other: Any) = other match {
+ case stp: SubTypePair =>
+ (tp1 =:= stp.tp1) && (tp2 =:= stp.tp2)
+ case _ =>
+ false
+ }
+ override def toString = tp1+" <:<? "+tp2
+ }
+
+// Helper Methods -------------------------------------------------------------
+
+ final val LubGlbMargin = 0
+
+ /** The maximum allowable depth of lubs or glbs over types `ts'
+ * This is the maximum depth of all types in the base type sequences
+ * of each of the types `ts', plus LubGlbMargin
+ */
+ def lubDepth(ts: List[Type]) = {
+ var d = 0
+ for (tp <- ts) d = math.max(d, tp.baseTypeSeqDepth)
+ d + LubGlbMargin
+ }
+
+ /** Is intersection of given types populated? That is,
+ * for all types tp1, tp2 in intersection
+ * for all common base classes bc of tp1 and tp2
+ * let bt1, bt2 be the base types of tp1, tp2 relative to class bc
+ * Then:
+ * bt1 and bt2 have the same prefix, and
+ * any corresponding non-variant type arguments of bt1 and bt2 are the same
+ */
+ def isPopulated(tp1: Type, tp2: Type): Boolean = {
+ def isConsistent(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
+ case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
+ assert(sym1 == sym2)
+ pre1 =:= pre2 &&
+ ((args1, args2, sym1.typeParams).zipped forall {
+ (arg1, arg2, tparam) =>
+ //if (tparam.variance == 0 && !(arg1 =:= arg2)) Console.println("inconsistent: "+arg1+"!="+arg2)//DEBUG
+ if (tparam.variance == 0) arg1 =:= arg2
+ else if (arg1.isInstanceOf[TypeVar])
+ // if left-hand argument is a typevar, make it compatible with variance
+ // this is for more precise pattern matching
+ // todo: work this in the spec of this method
+ // also: think what happens if there are embedded typevars?
+ if (tparam.variance < 0) arg1 <:< arg2 else arg2 <:< arg1
+ else true
+ })
+ case (et: ExistentialType, _) =>
+ et.withTypeVars(isConsistent(_, tp2))
+ case (_, et: ExistentialType) =>
+ et.withTypeVars(isConsistent(tp1, _))
+ }
+
+ def check(tp1: Type, tp2: Type) =
+ if (tp1.typeSymbol.isClass && tp1.typeSymbol.hasFlag(FINAL))
+ tp1 <:< tp2 || isNumericValueClass(tp1.typeSymbol) && isNumericValueClass(tp2.typeSymbol)
+ else tp1.baseClasses forall (bc =>
+ tp2.baseTypeIndex(bc) < 0 || isConsistent(tp1.baseType(bc), tp2.baseType(bc)))
+
+ check(tp1, tp2)/* && check(tp2, tp1)*/ // need to investgate why this can't be made symmetric -- neg/gadts1 fails, and run/existials also.
+ }
+
+ /** Does a pattern of type `patType' need an outer test when executed against
+ * selector type `selType' in context defined by `currentOwner'?
+ */
+ def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = {
+ def createDummyClone(pre: Type): Type = {
+ val dummy = currentOwner.enclClass.newValue(NoPosition, nme.ANYNAME).setInfo(pre.widen)
+ singleType(ThisType(currentOwner.enclClass), dummy)
+ }
+ def maybeCreateDummyClone(pre: Type, sym: Symbol): Type = pre match {
+ case SingleType(pre1, sym1) =>
+ if (sym1.isModule && sym1.isStatic) {
+ NoType
+ } else if (sym1.isModule && sym.owner == sym1.moduleClass) {
+ val pre2 = maybeCreateDummyClone(pre1, sym1)
+ if (pre2 eq NoType) pre2
+ else singleType(pre2, sym1)
+ } else {
+ createDummyClone(pre)
+ }
+ case ThisType(clazz) =>
+ if (clazz.isModuleClass)
+ maybeCreateDummyClone(clazz.typeOfThis, sym)
+ else if (sym.owner == clazz && (sym.hasFlag(PRIVATE) || sym.privateWithin == clazz))
+ NoType
+ else
+ createDummyClone(pre)
+ case _ =>
+ NoType
+ }
+ patType match {
+ case TypeRef(pre, sym, args) =>
+ val pre1 = maybeCreateDummyClone(pre, sym)
+ (pre1 ne NoType) && isPopulated(typeRef(pre1, sym, args), selType)
+ case _ =>
+ false
+ }
+ }
+
+ private var subsametypeRecursions: Int = 0
+
+ private def isUnifiable(pre1: Type, pre2: Type) =
+ (beginsWithTypeVarOrIsRefined(pre1) || beginsWithTypeVarOrIsRefined(pre2)) && (pre1 =:= pre2)
+
+ /** Returns true iff we are past phase specialize,
+ * sym1 and sym2 are two existential skolems with equal names and bounds,
+ * and pre1 and pre2 are equal prefixes
+ */
+ private def isSameSpecializedSkolem(sym1: Symbol, sym2: Symbol, pre1: Type, pre2: Type) = {
+ sym1.isExistentialSkolem && sym2.isExistentialSkolem &&
+ sym1.name == sym2.name &&
+ phase.specialized &&
+ sym1.info =:= sym2.info &&
+ pre1 =:= pre2
+ }
+
+ private def equalSymsAndPrefixes(sym1: Symbol, pre1: Type, sym2: Symbol, pre2: Type): Boolean =
+ if (sym1 == sym2) sym1.hasPackageFlag || phase.erasedTypes || pre1 =:= pre2
+ else (sym1.name == sym2.name) && isUnifiable(pre1, pre2)
+
+ /** Do `tp1' and `tp2' denote equivalent types?
+ */
+ def isSameType(tp1: Type, tp2: Type): Boolean = try {
+ incCounter(sametypeCount)
+ subsametypeRecursions += 1
+ undoLog undoUnless {
+ isSameType1(tp1, tp2)
+ }
+ } finally {
+ subsametypeRecursions -= 1
+ // XXX AM TODO: figure out when it is safe and needed to clear the log -- the commented approach below is too eager (it breaks #3281, #3866)
+ // it doesn't help to keep separate recursion counts for the three methods that now share it
+ // if (subsametypeRecursions == 0) undoLog.clear()
+ }
+
+ def isDifferentType(tp1: Type, tp2: Type): Boolean = try {
+ subsametypeRecursions += 1
+ undoLog undo { // undo type constraints that arise from operations in this block
+ !isSameType1(tp1, tp2)
+ }
+ } finally {
+ subsametypeRecursions -= 1
+ // XXX AM TODO: figure out when it is safe and needed to clear the log -- the commented approach below is too eager (it breaks #3281, #3866)
+ // it doesn't help to keep separate recursion counts for the three methods that now share it
+ // if (subsametypeRecursions == 0) undoLog.clear()
+ }
+
+ def isDifferentTypeConstructor(tp1: Type, tp2: Type): Boolean = tp1 match {
+ case TypeRef(pre1, sym1, _) =>
+ tp2 match {
+ case TypeRef(pre2, sym2, _) => sym1 != sym2 || isDifferentType(pre1, pre2)
+ case _ => true
+ }
+ case _ => true
+ }
+
+ def normalizePlus(tp: Type) =
+ if (isRawType(tp)) rawToExistential(tp)
+ else tp.normalize
+
+ /*
+ todo: change to:
+ def normalizePlus(tp: Type) = tp match {
+ case TypeRef(pre, sym, List()) =>
+ if (!sym.isInitialized) sym.rawInfo.load(sym)
+ if (sym.isJavaDefined && !sym.typeParams.isEmpty) rawToExistential(tp)
+ else tp.normalize
+ case _ => tp.normalize
+ }
+ */
+/*
+ private def isSameType0(tp1: Type, tp2: Type): Boolean = {
+ if (tp1 eq tp2) return true
+ ((tp1, tp2) match {
+ case (ErrorType, _) => true
+ case (WildcardType, _) => true
+ case (_, ErrorType) => true
+ case (_, WildcardType) => true
+
+ case (NoType, _) => false
+ case (NoPrefix, _) => tp2.typeSymbol.isPackageClass
+ case (_, NoType) => false
+ case (_, NoPrefix) => tp1.typeSymbol.isPackageClass
+
+ case (ThisType(sym1), ThisType(sym2))
+ if (sym1 == sym2) =>
+ true
+ case (SingleType(pre1, sym1), SingleType(pre2, sym2))
+ if (equalSymsAndPrefixes(sym1, pre1, sym2, pre2)) =>
+ true
+/*
+ case (SingleType(pre1, sym1), ThisType(sym2))
+ if (sym1.isModule &&
+ sym1.moduleClass == sym2 &&
+ pre1 =:= sym2.owner.thisType) =>
+ true
+ case (ThisType(sym1), SingleType(pre2, sym2))
+ if (sym2.isModule &&
+ sym2.moduleClass == sym1 &&
+ pre2 =:= sym1.owner.thisType) =>
+ true
+*/
+ case (ConstantType(value1), ConstantType(value2)) =>
+ value1 == value2
+ case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
+ equalSymsAndPrefixes(sym1, pre1, sym2, pre2) &&
+ ((tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) ||
+ isSameTypes(args1, args2))
+ // @M! normalize reduces higher-kinded case to PolyType's
+ case (RefinedType(parents1, ref1), RefinedType(parents2, ref2)) =>
+ def isSubScope(s1: Scope, s2: Scope): Boolean = s2.toList.forall {
+ sym2 =>
+ var e1 = s1.lookupEntry(sym2.name)
+ (e1 ne null) && {
+ val substSym = sym2.info.substThis(sym2.owner, e1.sym.owner.thisType)
+ var isEqual = false
+ while (!isEqual && (e1 ne null)) {
+ isEqual = e1.sym.info =:= substSym
+ e1 = s1.lookupNextEntry(e1)
+ }
+ isEqual
+ }
+ }
+ //Console.println("is same? " + tp1 + " " + tp2 + " " + tp1.typeSymbol.owner + " " + tp2.typeSymbol.owner)//DEBUG
+ isSameTypes(parents1, parents2) && isSubScope(ref1, ref2) && isSubScope(ref2, ref1)
+ case (MethodType(params1, res1), MethodType(params2, res2)) =>
+ // new dependent types: probably fix this, use substSym as done for PolyType
+ (isSameTypes(tp1.paramTypes, tp2.paramTypes) &&
+ res1 =:= res2 &&
+ tp1.isImplicit == tp2.isImplicit)
+ case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
+ // assert((tparams1 map (_.typeParams.length)) == (tparams2 map (_.typeParams.length)))
+ (tparams1.length == tparams2.length) && (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) && // @M looks like it might suffer from same problem as #2210
+ res1 =:= res2.substSym(tparams2, tparams1)
+ case (ExistentialType(tparams1, res1), ExistentialType(tparams2, res2)) =>
+ (tparams1.length == tparams2.length) && (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) && // @M looks like it might suffer from same problem as #2210
+ res1 =:= res2.substSym(tparams2, tparams1)
+ case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) =>
+ lo1 =:= lo2 && hi1 =:= hi2
+ case (BoundedWildcardType(bounds), _) =>
+ bounds containsType tp2
+ case (_, BoundedWildcardType(bounds)) =>
+ bounds containsType tp1
+ case (tv @ TypeVar(_,_), tp) =>
+ tv.registerTypeEquality(tp, true)
+ case (tp, tv @ TypeVar(_,_)) =>
+ tv.registerTypeEquality(tp, false)
+ case (AnnotatedType(_,_,_), _) =>
+ annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
+ case (_, AnnotatedType(_,_,_)) =>
+ annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
+ case (_: SingletonType, _: SingletonType) =>
+ var origin1 = tp1
+ while (origin1.underlying.isInstanceOf[SingletonType]) {
+ assert(origin1 ne origin1.underlying, origin1)
+ origin1 = origin1.underlying
+ }
+ var origin2 = tp2
+ while (origin2.underlying.isInstanceOf[SingletonType]) {
+ assert(origin2 ne origin2.underlying, origin2)
+ origin2 = origin2.underlying
+ }
+ ((origin1 ne tp1) || (origin2 ne tp2)) && (origin1 =:= origin2)
+ case _ =>
+ false
+ }) || {
+ val tp1n = normalizePlus(tp1)
+ val tp2n = normalizePlus(tp2)
+ ((tp1n ne tp1) || (tp2n ne tp2)) && isSameType(tp1n, tp2n)
+ }
+ }
+*/
+ private def isSameType1(tp1: Type, tp2: Type): Boolean = {
+ if ((tp1 eq tp2) ||
+ (tp1 eq ErrorType) || (tp1 eq WildcardType) ||
+ (tp2 eq ErrorType) || (tp2 eq WildcardType))
+ true
+ else if ((tp1 eq NoType) || (tp2 eq NoType))
+ false
+ else if (tp1 eq NoPrefix)
+ tp2.typeSymbol.isPackageClass
+ else if (tp2 eq NoPrefix)
+ tp1.typeSymbol.isPackageClass
+ else {
+ isSameType2(tp1, tp2) || {
+ val tp1n = normalizePlus(tp1)
+ val tp2n = normalizePlus(tp2)
+ ((tp1n ne tp1) || (tp2n ne tp2)) && isSameType(tp1n, tp2n)
+ }
+ }
+ }
+
+ def isSameType2(tp1: Type, tp2: Type): Boolean = {
+ tp1 match {
+ case tr1: TypeRef =>
+ tp2 match {
+ case tr2: TypeRef =>
+ return (equalSymsAndPrefixes(tr1.sym, tr1.pre, tr2.sym, tr2.pre) &&
+ ((tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) ||
+ isSameTypes(tr1.args, tr2.args))) ||
+ ((tr1.pre, tr2.pre) match {
+ case (tv @ TypeVar(_,_), _) => tv.registerTypeSelection(tr1.sym, tr2)
+ case (_, tv @ TypeVar(_,_)) => tv.registerTypeSelection(tr2.sym, tr1)
+ case _ => false
+ })
+ case _ =>
+ }
+ case tt1: ThisType =>
+ tp2 match {
+ case tt2: ThisType =>
+ if (tt1.sym == tt2.sym) return true
+ case _ =>
+ }
+ case st1: SingleType =>
+ tp2 match {
+ case st2: SingleType =>
+ if (equalSymsAndPrefixes(st1.sym, st1.pre, st2.sym, st2.pre)) return true
+ case _ =>
+ }
+ case ct1: ConstantType =>
+ tp2 match {
+ case ct2: ConstantType =>
+ return (ct1.value == ct2.value)
+ case _ =>
+ }
+ case rt1: RefinedType =>
+ tp2 match {
+ case rt2: RefinedType => //
+ def isSubScope(s1: Scope, s2: Scope): Boolean = s2.toList.forall {
+ sym2 =>
+ var e1 = s1.lookupEntry(sym2.name)
+ (e1 ne null) && {
+ val substSym = sym2.info.substThis(sym2.owner, e1.sym.owner.thisType)
+ var isEqual = false
+ while (!isEqual && (e1 ne null)) {
+ isEqual = e1.sym.info =:= substSym
+ e1 = s1.lookupNextEntry(e1)
+ }
+ isEqual
+ }
+ }
+ //Console.println("is same? " + tp1 + " " + tp2 + " " + tp1.typeSymbol.owner + " " + tp2.typeSymbol.owner)//DEBUG
+ return isSameTypes(rt1.parents, rt2.parents) && {
+ val decls1 = rt1.decls
+ val decls2 = rt2.decls
+ isSubScope(decls1, decls2) && isSubScope(decls2, decls1)
+ }
+ case _ =>
+ }
+ case mt1: MethodType =>
+ tp2 match {
+ case mt2: MethodType =>
+ // DEPMETTODO new dependent types: probably fix this, use substSym as done for PolyType
+ return isSameTypes(mt1.paramTypes, mt2.paramTypes) &&
+ mt1.resultType =:= mt2.resultType &&
+ mt1.isImplicit == mt2.isImplicit
+ // note: no case NullaryMethodType(restpe) => return mt1.params.isEmpty && mt1.resultType =:= restpe
+ case _ =>
+ }
+ case NullaryMethodType(restpe1) =>
+ tp2 match {
+ // note: no case mt2: MethodType => return mt2.params.isEmpty && restpe =:= mt2.resultType
+ case NullaryMethodType(restpe2) =>
+ return restpe1 =:= restpe2
+ case _ =>
+ }
+ case PolyType(tparams1, res1) =>
+ tp2 match {
+ case PolyType(tparams2, res2) =>
+// assert((tparams1 map (_.typeParams.length)) == (tparams2 map (_.typeParams.length)))
+ // @M looks like it might suffer from same problem as #2210
+ return (
+ (sameLength(tparams1, tparams2)) && // corresponds does not check length of two sequences before checking the predicate
+ (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) &&
+ res1 =:= res2.substSym(tparams2, tparams1)
+ )
+ case _ =>
+ }
+ case ExistentialType(tparams1, res1) =>
+ tp2 match {
+ case ExistentialType(tparams2, res2) =>
+ // @M looks like it might suffer from same problem as #2210
+ return (
+ // corresponds does not check length of two sequences before checking the predicate -- faster & needed to avoid crasher in #2956
+ sameLength(tparams1, tparams2) &&
+ (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) &&
+ res1 =:= res2.substSym(tparams2, tparams1)
+ )
+ case _ =>
+ }
+ case TypeBounds(lo1, hi1) =>
+ tp2 match {
+ case TypeBounds(lo2, hi2) =>
+ return lo1 =:= lo2 && hi1 =:= hi2
+ case _ =>
+ }
+ case BoundedWildcardType(bounds) =>
+ return bounds containsType tp2
+ case _ =>
+ }
+ tp2 match {
+ case BoundedWildcardType(bounds) =>
+ return bounds containsType tp1
+ case _ =>
+ }
+ tp1 match {
+ case tv @ TypeVar(_,_) =>
+ return tv.registerTypeEquality(tp2, true)
+ case _ =>
+ }
+ tp2 match {
+ case tv @ TypeVar(_,_) =>
+ return tv.registerTypeEquality(tp1, false)
+ case _ =>
+ }
+ tp1 match {
+ case _: AnnotatedType =>
+ return annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
+ case _ =>
+ }
+ tp2 match {
+ case _: AnnotatedType =>
+ return annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
+ case _ =>
+ }
+ tp1 match {
+ case _: SingletonType =>
+ tp2 match {
+ case _: SingletonType =>
+ @inline def chaseDealiasedUnderlying(tp: Type): Type = {
+ var origin = tp
+ var next = origin.underlying.dealias
+ while (next.isInstanceOf[SingletonType]) {
+ assert(origin ne next, origin)
+ origin = next
+ next = origin.underlying.dealias
+ }
+ origin
+ }
+ val origin1 = chaseDealiasedUnderlying(tp1)
+ val origin2 = chaseDealiasedUnderlying(tp2)
+ ((origin1 ne tp1) || (origin2 ne tp2)) && (origin1 =:= origin2)
+ case _ =>
+ false
+ }
+ case _ =>
+ false
+ }
+ }
+
+ /** Are `tps1' and `tps2' lists of pairwise equivalent
+ * types?
+ */
+ def isSameTypes(tps1: List[Type], tps2: List[Type]): Boolean = (tps1 corresponds tps2)(_ =:= _)
+
+ /** True if two lists have the same length. Since calling length on linear sequences
+ * is O(n), it is an inadvisable way to test length equality.
+ */
+ final def sameLength(xs1: List[_], xs2: List[_]) = compareLengths(xs1, xs2) == 0
+ @tailrec final def compareLengths(xs1: List[_], xs2: List[_]): Int =
+ if (xs1.isEmpty) { if (xs2.isEmpty) 0 else -1 }
+ else if (xs2.isEmpty) 1
+ else compareLengths(xs1.tail, xs2.tail)
+
+ /** Again avoiding calling length, but the lengthCompare interface is clunky.
+ */
+ final def hasLength(xs: List[_], len: Int) = xs.lengthCompare(len) == 0
+
+ private val pendingSubTypes = new mutable.HashSet[SubTypePair]
+ private var basetypeRecursions: Int = 0
+ private val pendingBaseTypes = new mutable.HashSet[Type]
+
+ def isSubType(tp1: Type, tp2: Type): Boolean = isSubType(tp1, tp2, AnyDepth)
+
+ def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean = try {
+ subsametypeRecursions += 1
+
+ undoLog undoUnless { // if subtype test fails, it should not affect constraints on typevars
+ if (subsametypeRecursions >= LogPendingSubTypesThreshold) {
+ val p = new SubTypePair(tp1, tp2)
+ if (pendingSubTypes(p))
+ false
+ else
+ try {
+ pendingSubTypes += p
+ isSubType2(tp1, tp2, depth)
+ } finally {
+ pendingSubTypes -= p
+ }
+ } else {
+ isSubType2(tp1, tp2, depth)
+ }
+ }
+ } finally {
+ subsametypeRecursions -= 1
+ // XXX AM TODO: figure out when it is safe and needed to clear the log -- the commented approach below is too eager (it breaks #3281, #3866)
+ // it doesn't help to keep separate recursion counts for the three methods that now share it
+ // if (subsametypeRecursions == 0) undoLog.clear()
+ }
+
+ /** Does this type have a prefix that begins with a type variable,
+ * or is it a refinement type? For type prefixes that fulfil this condition,
+ * type selections with the same name of equal (wrt) =:= prefixes are
+ * considered equal wrt =:=
+ */
+ def beginsWithTypeVarOrIsRefined(tp: Type): Boolean = tp match {
+ case SingleType(pre, sym) =>
+ !(sym hasFlag PACKAGE) && beginsWithTypeVarOrIsRefined(pre)
+ case tv@TypeVar(_, constr) =>
+ !tv.instValid || beginsWithTypeVarOrIsRefined(constr.inst)
+ case RefinedType(_, _) =>
+ true
+ case _ =>
+ false
+ }
+
+ def instTypeVar(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) =>
+ typeRef(instTypeVar(pre), sym, args)
+ case SingleType(pre, sym) =>
+ singleType(instTypeVar(pre), sym)
+ case TypeVar(_, constr) =>
+ instTypeVar(constr.inst)
+ case _ =>
+ tp
+ }
+
+ def isErrorOrWildcard(tp: Type) = (tp eq ErrorType) || (tp eq WildcardType)
+
+ def isSingleType(tp: Type) = tp match {
+ case ThisType(_) | SuperType(_, _) | SingleType(_, _) => true
+ case _ => false
+ }
+
+ def isConstantType(tp: Type) = tp match {
+ case ConstantType(_) => true
+ case _ => false
+ }
+
+ // @assume tp1.isHigherKinded || tp2.isHigherKinded
+ def isHKSubType0(tp1: Type, tp2: Type, depth: Int): Boolean = (
+ tp1.typeSymbol == NothingClass
+ ||
+ tp2.typeSymbol == AnyClass // @M Any and Nothing are super-type resp. subtype of every well-kinded type
+ || // @M! normalize reduces higher-kinded case to PolyType's
+ ((tp1.normalize.withoutAnnotations , tp2.normalize.withoutAnnotations) match {
+ case (PolyType(tparams1, res1), PolyType(tparams2, res2)) => // @assume tp1.isHigherKinded && tp2.isHigherKinded (as they were both normalized to PolyType)
+ sameLength(tparams1, tparams2) && {
+ if (tparams1.head.owner.isMethod) { // fast-path: polymorphic method type -- type params cannot be captured
+ (tparams1 corresponds tparams2)((p1, p2) => p2.info.substSym(tparams2, tparams1) <:< p1.info) &&
+ res1 <:< res2.substSym(tparams2, tparams1)
+ } else { // normalized higher-kinded type
+ //@M for an example of why we need to generate fresh symbols, see neg/tcpoly_ticket2101.scala
+ val tpsFresh = cloneSymbols(tparams1)
+
+ (tparams1 corresponds tparams2)((p1, p2) =>
+ p2.info.substSym(tparams2, tpsFresh) <:< p1.info.substSym(tparams1, tpsFresh)) &&
+ res1.substSym(tparams1, tpsFresh) <:< res2.substSym(tparams2, tpsFresh)
+
+ //@M the forall in the previous test could be optimised to the following,
+ // but not worth the extra complexity since it only shaves 1s from quick.comp
+ // (List.forall2(tpsFresh/*optimisation*/, tparams2)((p1, p2) =>
+ // p2.info.substSym(tparams2, tpsFresh) <:< p1.info /*optimisation, == (p1 from tparams1).info.substSym(tparams1, tpsFresh)*/) &&
+ // this optimisation holds because inlining cloneSymbols in `val tpsFresh = cloneSymbols(tparams1)` gives:
+ // val tpsFresh = tparams1 map (_.cloneSymbol)
+ // for (tpFresh <- tpsFresh) tpFresh.setInfo(tpFresh.info.substSym(tparams1, tpsFresh))
+ }
+ } && annotationsConform(tp1.normalize, tp2.normalize)
+ case (_, _) => false // @assume !tp1.isHigherKinded || !tp2.isHigherKinded
+ // --> thus, cannot be subtypes (Any/Nothing has already been checked)
+ }))
+
+ /** True if all three arguments have the same number of elements and
+ * the function is true for all the triples.
+ */
+ @tailrec final def corresponds3[A, B, C](xs1: List[A], xs2: List[B], xs3: List[C], f: (A, B, C) => Boolean): Boolean = {
+ if (xs1.isEmpty) xs2.isEmpty && xs3.isEmpty
+ else !xs2.isEmpty && !xs3.isEmpty && f(xs1.head, xs2.head, xs3.head) && corresponds3(xs1.tail, xs2.tail, xs3.tail, f)
+ }
+
+ def isSubArg(t1: Type, t2: Type, variance: Int) =
+ (variance > 0 || t2 <:< t1) && (variance < 0 || t1 <:< t2)
+
+ def isSubArgs(tps1: List[Type], tps2: List[Type], tparams: List[Symbol]): Boolean =
+ corresponds3(tps1, tps2, tparams map (_.variance), isSubArg)
+
+ def differentOrNone(tp1: Type, tp2: Type) = if (tp1 eq tp2) NoType else tp1
+
+ /** Does type `tp1' conform to `tp2'?
+ */
+ private def isSubType2(tp1: Type, tp2: Type, depth: Int): Boolean = {
+ if ((tp1 eq tp2) || isErrorOrWildcard(tp1) || isErrorOrWildcard(tp2)) return true
+ if ((tp1 eq NoType) || (tp2 eq NoType)) return false
+ if (tp1 eq NoPrefix) return (tp2 eq NoPrefix) || tp2.typeSymbol.isPackageClass
+ if (tp2 eq NoPrefix) return tp1.typeSymbol.isPackageClass
+ if (isSingleType(tp1) && isSingleType(tp2) || isConstantType(tp1) && isConstantType(tp2)) return tp1 =:= tp2
+ if (tp1.isHigherKinded || tp2.isHigherKinded) return isHKSubType0(tp1, tp2, depth)
+
+ /** First try, on the right:
+ * - unwrap Annotated types, BoundedWildcardTypes,
+ * - bind TypeVars on the right, if lhs is not Annotated nor BoundedWildcard
+ * - handle common cases for first-kind TypeRefs on both sides as a fast path.
+ */
+ def firstTry = tp2 match {
+ // fast path: two typerefs, none of them HK
+ case tr2: TypeRef =>
+ tp1 match {
+ case tr1: TypeRef =>
+ val sym1 = tr1.sym
+ val sym2 = tr2.sym
+ val pre1 = tr1.pre
+ val pre2 = tr2.pre
+ (((if (sym1 == sym2) phase.erasedTypes || pre1 <:< pre2
+ else (sym1.name == sym2.name && !sym1.isModuleClass && !sym2.isModuleClass &&
+ (isUnifiable(pre1, pre2) || isSameSpecializedSkolem(sym1, sym2, pre1, pre2)))) &&
+ isSubArgs(tr1.args, tr2.args, sym1.typeParams))
+ ||
+ sym2.isClass && {
+ val base = tr1 baseType sym2
+ (base ne tr1) && base <:< tr2
+ }
+ ||
+ thirdTryRef(tr1, tr2))
+ case _ =>
+ secondTry
+ }
+ case AnnotatedType(_, _, _) =>
+ tp1.withoutAnnotations <:< tp2.withoutAnnotations && annotationsConform(tp1, tp2)
+ case BoundedWildcardType(bounds) =>
+ tp1 <:< bounds.hi
+ case tv2 @ TypeVar(_, constr2) =>
+ tp1 match {
+ case AnnotatedType(_, _, _) | BoundedWildcardType(_) =>
+ secondTry
+ case _ =>
+ tv2.registerBound(tp1, true)
+ }
+ case _ =>
+ secondTry
+ }
+
+ /** Second try, on the left:
+ * - unwrap AnnotatedTypes, BoundedWildcardTypes,
+ * - bind typevars,
+ * - handle existential types by skolemization.
+ */
+ def secondTry = tp1 match {
+ case AnnotatedType(_, _, _) =>
+ tp1.withoutAnnotations <:< tp2.withoutAnnotations && annotationsConform(tp1, tp2)
+ case BoundedWildcardType(bounds) =>
+ tp1.bounds.lo <:< tp2
+ case tv @ TypeVar(_,_) =>
+ tv.registerBound(tp2, false)
+ case ExistentialType(_, _) =>
+ try {
+ skolemizationLevel += 1
+ tp1.skolemizeExistential <:< tp2
+ } finally {
+ skolemizationLevel -= 1
+ }
+ case _ =>
+ thirdTry
+ }
+
+ def thirdTryRef(tp1: Type, tp2: TypeRef): Boolean = {
+ val sym2 = tp2.sym
+ sym2 match {
+ case NotNullClass => tp1.isNotNull
+ case SingletonClass => tp1.isStable || fourthTry
+ case _: ClassSymbol =>
+ if (isRaw(sym2, tp2.args))
+ isSubType(tp1, rawToExistential(tp2), depth)
+ else if (sym2.name == tpnme.REFINE_CLASS_NAME)
+ isSubType(tp1, sym2.info, depth)
+ else
+ fourthTry
+ case _: TypeSymbol =>
+ if (sym2 hasFlag DEFERRED) {
+ val tp2a = tp2.bounds.lo
+ isDifferentTypeConstructor(tp2, tp2a) && tp1 <:< tp2a || fourthTry
+ } else {
+ isSubType(tp1.normalize, tp2.normalize, depth)
+ }
+ case _ =>
+ fourthTry
+ }
+ }
+
+ /** Third try, on the right:
+ * - decompose refined types.
+ * - handle typerefs, existentials, and notnull types.
+ * - handle left+right method types, polytypes, typebounds
+ */
+ def thirdTry = tp2 match {
+ case tr2: TypeRef =>
+ thirdTryRef(tp1, tr2)
+ case rt2: RefinedType =>
+ (rt2.parents forall (tp1 <:< _)) &&
+ (rt2.decls.toList forall tp1.specializes)
+ case et2: ExistentialType =>
+ et2.withTypeVars(tp1 <:< _, depth) || fourthTry
+ case nn2: NotNullType =>
+ tp1.isNotNull && tp1 <:< nn2.underlying
+ case mt2: MethodType =>
+ tp1 match {
+ case mt1 @ MethodType(params1, res1) =>
+ val params2 = mt2.params
+ val res2 = mt2.resultType
+ (sameLength(params1, params2) &&
+ matchingParams(params1, params2, mt1.isJava, mt2.isJava) &&
+ (res1 <:< res2) &&
+ mt1.isImplicit == mt2.isImplicit)
+ // TODO: if mt1.params.isEmpty, consider NullaryMethodType?
+ case _ =>
+ false
+ }
+ case pt2 @ NullaryMethodType(_) =>
+ tp1 match {
+ // TODO: consider MethodType mt for which mt.params.isEmpty??
+ case pt1 @ NullaryMethodType(_) =>
+ pt1.resultType <:< pt2.resultType
+ case _ =>
+ false
+ }
+ case TypeBounds(lo2, hi2) =>
+ tp1 match {
+ case TypeBounds(lo1, hi1) =>
+ lo2 <:< lo1 && hi1 <:< hi2
+ case _ =>
+ false
+ }
+ case _ =>
+ fourthTry
+ }
+
+ /** Fourth try, on the left:
+ * - handle typerefs, refined types, notnull and singleton types.
+ */
+ def fourthTry = tp1 match {
+ case tr1 @ TypeRef(_, sym1, _) =>
+ sym1 match {
+ case NothingClass => true
+ case NullClass =>
+ tp2 match {
+ case TypeRef(_, sym2, _) =>
+ sym2.isClass && (sym2 isNonBottomSubClass ObjectClass) &&
+ !(tp2.normalize.typeSymbol isNonBottomSubClass NotNullClass)
+ case _ =>
+ isSingleType(tp2) && tp1 <:< tp2.widen
+ }
+ case _: ClassSymbol =>
+ if (isRaw(sym1, tr1.args))
+ isSubType(rawToExistential(tp1), tp2, depth)
+ else
+ sym1.name == tpnme.REFINE_CLASS_NAME &&
+ isSubType(sym1.info, tp2, depth)
+ case _: TypeSymbol =>
+ if (sym1 hasFlag DEFERRED) {
+ val tp1a = tp1.bounds.hi
+ isDifferentTypeConstructor(tp1, tp1a) && tp1a <:< tp2
+ } else {
+ isSubType(tp1.normalize, tp2.normalize, depth)
+ }
+ case _ =>
+ false
+ }
+ case RefinedType(parents1, _) =>
+ parents1 exists (_ <:< tp2)
+ case _: SingletonType | _: NotNullType =>
+ tp1.underlying <:< tp2
+ case _ =>
+ false
+ }
+
+ firstTry
+ }
+
+ /** Are `tps1' and `tps2' lists of equal length such
+ * that all elements of `tps1' conform to corresponding elements
+ * of `tps2'?
+ */
+ def isSubTypes(tps1: List[Type], tps2: List[Type]): Boolean = (tps1 corresponds tps2)(_ <:< _)
+
+ /** Does type `tp' implement symbol `sym' with same or
+ * stronger type? Exact only if `sym' is a member of some
+ * refinement type, otherwise we might return false negatives.
+ */
+ def specializesSym(tp: Type, sym: Symbol): Boolean =
+ tp.typeSymbol == NothingClass ||
+ tp.typeSymbol == NullClass && (sym.owner isSubClass ObjectClass) ||
+ (tp.nonPrivateMember(sym.name).alternatives exists
+ (alt => sym == alt || specializesSym(tp.narrow, alt, sym.owner.thisType, sym)))
+
+ /** Does member `sym1' of `tp1' have a stronger type
+ * than member `sym2' of `tp2'?
+ */
+ private def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol): Boolean = {
+ val info1 = tp1.memberInfo(sym1)
+ val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1)
+ //System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG
+ sym2.isTerm && (info1 <:< info2) /*&& (!sym2.isStable || sym1.isStable) */ ||
+ sym2.isAbstractType && {
+ val memberTp1 = tp1.memberType(sym1)
+ // println("kinds conform? "+(memberTp1, tp1, sym2, kindsConform(List(sym2), List(memberTp1), tp2, sym2.owner)))
+ info2.bounds.containsType(memberTp1) &&
+ kindsConform(List(sym2), List(memberTp1), tp1, sym1.owner)
+ } ||
+ sym2.isAliasType && tp2.memberType(sym2).substThis(tp2.typeSymbol, tp1) =:= tp1.memberType(sym1) //@MAT ok
+ }
+
+ /** A function implementing `tp1' matches `tp2' */
+ final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
+ def matchesQuantified(tparams1: List[Symbol], tparams2: List[Symbol], res1: Type, res2: Type): Boolean = (
+ sameLength(tparams1, tparams2) &&
+ matchesType(res1, res2.substSym(tparams2, tparams1), alwaysMatchSimple)
+ )
+ def lastTry =
+ tp2 match {
+ case ExistentialType(_, res2) if alwaysMatchSimple =>
+ matchesType(tp1, res2, true)
+ case MethodType(_, _) =>
+ false
+ case PolyType(tparams2, res2) =>
+ tparams2.isEmpty && matchesType(tp1, res2, alwaysMatchSimple)
+ case _ =>
+ alwaysMatchSimple || tp1 =:= tp2
+ }
+ tp1 match {
+ case mt1 @ MethodType(params1, res1) =>
+ tp2 match {
+ case mt2 @ MethodType(params2, res2) =>
+ sameLength(params1, params2) && // useful pre-screening optimization
+ matchingParams(params1, params2, mt1.isJava, mt2.isJava) &&
+ matchesType(res1, res2, alwaysMatchSimple) &&
+ mt1.isImplicit == mt2.isImplicit
+ case NullaryMethodType(res2) =>
+ if (params1.isEmpty) matchesType(res1, res2, alwaysMatchSimple)
+ else matchesType(tp1, res2, alwaysMatchSimple)
+ case ExistentialType(_, res2) =>
+ alwaysMatchSimple && matchesType(tp1, res2, true)
+ case _ =>
+ false
+ }
+ case mt1 @ NullaryMethodType(res1) =>
+ tp2 match {
+ case mt2 @ MethodType(Nil, res2) => // could never match if params nonEmpty, and !mt2.isImplicit is implied by empty param list
+ matchesType(res1, res2, alwaysMatchSimple)
+ case NullaryMethodType(res2) =>
+ matchesType(res1, res2, alwaysMatchSimple)
+ case ExistentialType(_, res2) =>
+ alwaysMatchSimple && matchesType(tp1, res2, true)
+ case _ =>
+ matchesType(res1, tp2, alwaysMatchSimple)
+ }
+ case PolyType(tparams1, res1) =>
+ tp2 match {
+ case PolyType(tparams2, res2) =>
+ matchesQuantified(tparams1, tparams2, res1, res2)
+ case ExistentialType(_, res2) =>
+ alwaysMatchSimple && matchesType(tp1, res2, true)
+ case _ =>
+ false // remember that tparams1.nonEmpty is now an invariant of PolyType
+ }
+ case ExistentialType(tparams1, res1) =>
+ tp2 match {
+ case ExistentialType(tparams2, res2) =>
+ matchesQuantified(tparams1, tparams2, res1, res2)
+ case _ =>
+ if (alwaysMatchSimple) matchesType(res1, tp2, true)
+ else lastTry
+ }
+ case _ =>
+ lastTry
+ }
+ }
+
+/** matchesType above is an optimized version of the following implementation:
+
+ def matchesType2(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
+ def matchesQuantified(tparams1: List[Symbol], tparams2: List[Symbol], res1: Type, res2: Type): Boolean =
+ tparams1.length == tparams2.length &&
+ matchesType(res1, res2.substSym(tparams2, tparams1), alwaysMatchSimple)
+ (tp1, tp2) match {
+ case (MethodType(params1, res1), MethodType(params2, res2)) =>
+ params1.length == params2.length && // useful pre-secreening optimization
+ matchingParams(params1, params2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
+ matchesType(res1, res2, alwaysMatchSimple) &&
+ tp1.isImplicit == tp2.isImplicit
+ case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
+ matchesQuantified(tparams1, tparams2, res1, res2)
+ case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) =>
+ matchesType(rtp1, rtp2, alwaysMatchSimple)
+ case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) =>
+ matchesType(rtp1, rtp2, alwaysMatchSimple)
+ case (ExistentialType(tparams1, res1), ExistentialType(tparams2, res2)) =>
+ matchesQuantified(tparams1, tparams2, res1, res2)
+ case (ExistentialType(_, res1), _) if alwaysMatchSimple =>
+ matchesType(res1, tp2, alwaysMatchSimple)
+ case (_, ExistentialType(_, res2)) if alwaysMatchSimple =>
+ matchesType(tp1, res2, alwaysMatchSimple)
+ case (NullaryMethodType(rtp1), _) =>
+ matchesType(rtp1, tp2, alwaysMatchSimple)
+ case (_, NullaryMethodType(rtp2)) =>
+ matchesType(tp1, rtp2, alwaysMatchSimple)
+ case (MethodType(_, _), _) => false
+ case (PolyType(_, _), _) => false
+ case (_, MethodType(_, _)) => false
+ case (_, PolyType(_, _)) => false
+ case _ =>
+ alwaysMatchSimple || tp1 =:= tp2
+ }
+ }
+*/
+
+ /** Are `syms1' and `syms2' parameter lists with pairwise equivalent types? */
+ private def matchingParams(syms1: List[Symbol], syms2: List[Symbol], syms1isJava: Boolean, syms2isJava: Boolean): Boolean = syms1 match {
+ case Nil =>
+ syms2.isEmpty
+ case sym1 :: rest1 =>
+ syms2 match {
+ case Nil =>
+ false
+ case sym2 :: rest2 =>
+ val tp1 = sym1.tpe
+ val tp2 = sym2.tpe
+ (tp1 =:= tp2 ||
+ syms1isJava && tp2.typeSymbol == ObjectClass && tp1.typeSymbol == AnyClass ||
+ syms2isJava && tp1.typeSymbol == ObjectClass && tp2.typeSymbol == AnyClass) &&
+ matchingParams(rest1, rest2, syms1isJava, syms2isJava)
+ }
+ }
+
+ /** like map2, but returns list `xs' itself - instead of a copy - if function
+ * `f' maps all elements to themselves.
+ */
+ def map2Conserve[A <: AnyRef, B](xs: List[A], ys: List[B])(f: (A, B) => A): List[A] =
+ if (xs.isEmpty) xs
+ else {
+ val x1 = f(xs.head, ys.head)
+ val xs1 = map2Conserve(xs.tail, ys.tail)(f)
+ if ((x1 eq xs.head) && (xs1 eq xs.tail)) xs
+ else x1 :: xs1
+ }
+
+ /** Solve constraint collected in types `tvars'.
+ *
+ * @param tvars All type variables to be instantiated.
+ * @param tparams The type parameters corresponding to `tvars'
+ * @param variances The variances of type parameters; need to reverse
+ * solution direction for all contravariant variables.
+ * @param upper When `true' search for max solution else min.
+ */
+ def solve(tvars: List[TypeVar], tparams: List[Symbol],
+ variances: List[Int], upper: Boolean): Boolean =
+ solve(tvars, tparams, variances, upper, AnyDepth)
+
+ def solve(tvars: List[TypeVar], tparams: List[Symbol],
+ variances: List[Int], upper: Boolean, depth: Int): Boolean = {
+ val config = tvars zip (tparams zip variances)
+
+ def solveOne(tvar: TypeVar, tparam: Symbol, variance: Int) {
+ if (tvar.constr.inst == NoType) {
+ val up = if (variance != CONTRAVARIANT) upper else !upper
+ tvar.constr.inst = null
+ val bound: Type = if (up) tparam.info.bounds.hi else tparam.info.bounds.lo
+ //Console.println("solveOne0(tv, tp, v, b)="+(tvar, tparam, variance, bound))
+ var cyclic = bound contains tparam
+ for ((tvar2, (tparam2, variance2)) <- config) {
+ if (tparam2 != tparam &&
+ ((bound contains tparam2) ||
+ up && (tparam2.info.bounds.lo =:= tparam.tpe) ||
+ !up && (tparam2.info.bounds.hi =:= tparam.tpe))) {
+ if (tvar2.constr.inst eq null) cyclic = true
+ solveOne(tvar2, tparam2, variance2)
+ }
+ }
+ if (!cyclic) {
+ if (up) {
+ if (bound.typeSymbol != AnyClass)
+ tvar addHiBound bound.instantiateTypeParams(tparams, tvars)
+ for (tparam2 <- tparams)
+ tparam2.info.bounds.lo.dealias match {
+ case TypeRef(_, `tparam`, _) =>
+ tvar addHiBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
+ case _ =>
+ }
+ } else {
+ if (bound.typeSymbol != NothingClass && bound.typeSymbol != tparam) {
+ tvar addLoBound bound.instantiateTypeParams(tparams, tvars)
+ }
+ for (tparam2 <- tparams)
+ tparam2.info.bounds.hi.dealias match {
+ case TypeRef(_, `tparam`, _) =>
+ tvar addLoBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
+ case _ =>
+ }
+ }
+ }
+ tvar.constr.inst = NoType // necessary because hibounds/lobounds may contain tvar
+
+ //println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen)))
+
+ tvar setInst (
+ if (up) {
+ if (depth != AnyDepth) glb(tvar.constr.hiBounds, depth) else glb(tvar.constr.hiBounds)
+ } else {
+ if (depth != AnyDepth) lub(tvar.constr.loBounds, depth) else lub(tvar.constr.loBounds)
+ })
+
+ //Console.println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen))+" = "+tvar.constr.inst)//@MDEBUG
+ }
+ }
+
+ // println("solving "+tvars+"/"+tparams+"/"+(tparams map (_.info)))
+ for ((tvar, (tparam, variance)) <- config)
+ solveOne(tvar, tparam, variance)
+
+ tvars forall (tvar => tvar.constr.isWithinBounds(tvar.constr.inst))
+ }
+
+ /** Do type arguments `targs' conform to formal parameters
+ * `tparams'?
+ *
+ * @param tparams ...
+ * @param targs ...
+ * @return ...
+ */
+ def isWithinBounds(pre: Type, owner: Symbol, tparams: List[Symbol], targs: List[Type]): Boolean = {
+ var bounds = instantiatedBounds(pre, owner, tparams, targs)
+ if (targs.exists(_.annotations.nonEmpty))
+ bounds = adaptBoundsToAnnotations(bounds, tparams, targs)
+ (bounds corresponds targs)(_ containsType _)
+ }
+
+ def instantiatedBounds(pre: Type, owner: Symbol, tparams: List[Symbol], targs: List[Type]): List[TypeBounds] =
+ tparams map (_.info.asSeenFrom(pre, owner).instantiateTypeParams(tparams, targs).bounds)
+
+// Lubs and Glbs ---------------------------------------------------------
+
+ /** The least sorted upwards closed upper bound of a non-empty list
+ * of lists of types relative to the following ordering <= between lists of types:
+ *
+ * xs <= ys iff forall y in ys exists x in xs such that x <: y
+ *
+ * @See baseTypeSeq for a definition of sorted and upwards closed.
+ */
+ private def lubList(tss: List[List[Type]], depth: Int): List[Type] =
+ if (tss.tail.isEmpty) tss.head
+ else if (tss exists (_.isEmpty)) List()
+ else {
+ val ts0 = tss map (_.head)
+ val sym = minSym(ts0)
+ if (ts0 forall (_.typeSymbol == sym))
+ mergePrefixAndArgs(elimSub(ts0, depth), 1, depth).toList ::: lubList(tss map (_.tail), depth)
+ else
+ lubList(tss map (ts => if (ts.head.typeSymbol == sym) ts.tail else ts), depth)
+ }
+
+ private def lubBaseTypeSeq(tss: List[BaseTypeSeq], depth: Int): List[Type] =
+ lubList(tss map (_.toList), depth)
+
+ /** The minimal symbol (wrt Symbol.isLess) of a list of types */
+ private def minSym(tps: List[Type]): Symbol =
+ (tps.head.typeSymbol /: tps.tail) {
+ (sym1, tp2) => if (tp2.typeSymbol isLess sym1) tp2.typeSymbol else sym1
+ }
+
+ /** A minimal type list which has a given list of types as its base type sequence */
+ def spanningTypes(ts: List[Type]): List[Type] = ts match {
+ case List() => List()
+ case first :: rest =>
+ first :: spanningTypes(
+ rest filter (t => !first.typeSymbol.isSubClass(t.typeSymbol)))
+ }
+
+ /** Eliminate from list of types all elements which are a supertype
+ * of some other element of the list. */
+ private def elimSuper(ts: List[Type]): List[Type] = ts match {
+ case List() => List()
+ case t :: ts1 =>
+ val rest = elimSuper(ts1 filter (t1 => !(t <:< t1)))
+ if (rest exists (t1 => t1 <:< t)) rest else t :: rest
+ }
+
+ /** A collector that tests for existential types appearing at given variance in a type */
+ class ContainsVariantExistentialCollector(v: Int) extends TypeCollector(false) {
+ def traverse(tp: Type) = tp match {
+ case ExistentialType(_, _) if (variance == v) => result = true
+ case _ => mapOver(tp)
+ }
+ def init() = {
+ variance = 1
+ this
+ }
+ }
+
+ val containsCovariantExistentialCollector = new ContainsVariantExistentialCollector(1)
+ val containsContravariantExistentialCollector = new ContainsVariantExistentialCollector(-1)
+
+ /** Eliminate from list of types all elements which are a subtype
+ * of some other element of the list. */
+ private def elimSub(ts: List[Type], depth: Int): List[Type] = {
+ def elimAnonymousClass(t: Type) = t match {
+ case TypeRef(pre, clazz, List()) if clazz.isAnonymousClass =>
+ clazz.classBound.asSeenFrom(pre, clazz.owner)
+ case _ =>
+ t
+ }
+ def elimSub0(ts: List[Type]): List[Type] = ts match {
+ case List() => List()
+ case t :: ts1 =>
+ val rest = elimSub0(ts1 filter (t1 => !isSubType(t1, t, decr(depth))))
+ if (rest exists (t1 => isSubType(t, t1, decr(depth)))) rest else t :: rest
+ }
+ val ts0 = elimSub0(ts)
+ if (ts0.isEmpty || ts0.tail.isEmpty) ts0
+ else {
+ val ts1 = ts0 mapConserve (t => elimAnonymousClass(t.underlying))
+ if (ts1 eq ts0) ts0
+ else elimSub(ts1, depth)
+ }
+ }
+
+ private def stripExistentialsAndTypeVars(ts: List[Type]): (List[Type], List[Symbol]) = {
+ val quantified = ts flatMap {
+ case ExistentialType(qs, _) => qs
+ case t => List()
+ }
+ def stripType(tp: Type) = tp match {
+ case ExistentialType(_, res) =>
+ res
+ case TypeVar(_, constr) =>
+ if (constr.instValid) constr.inst
+ else abort("trying to do lub/glb of typevar "+tp)
+ case t => t
+ }
+ val strippedTypes = ts mapConserve stripType
+ (strippedTypes, quantified)
+ }
+
+ def weakLub(ts: List[Type]) =
+ if (ts.nonEmpty && (ts forall isNumericValueType)) (numericLub(ts), true)
+ else if (ts.nonEmpty && (ts exists (_.annotations.nonEmpty)))
+ (annotationsLub(lub(ts map (_.withoutAnnotations)), ts), true)
+ else (lub(ts), false)
+
+ def weakGlb(ts: List[Type]) = {
+ if (ts.nonEmpty && (ts forall isNumericValueType)) {
+ val nglb = numericGlb(ts)
+ if (nglb != NoType) (nglb, true)
+ else (glb(ts), false)
+ } else if (ts.nonEmpty && (ts exists (_.annotations.nonEmpty))) {
+ (annotationsGlb(glb(ts map (_.withoutAnnotations)), ts), true)
+ } else (glb(ts), false)
+ }
+
+ def numericLub(ts: List[Type]) =
+ ts reduceLeft ((t1, t2) =>
+ if (isNumericSubType(t1, t2)) t2
+ else if (isNumericSubType(t2, t1)) t1
+ else IntClass.tpe)
+
+ def numericGlb(ts: List[Type]) =
+ ts reduceLeft ((t1, t2) =>
+ if (isNumericSubType(t1, t2)) t1
+ else if (isNumericSubType(t2, t1)) t2
+ else NoType)
+
+ def isWeakSubType(tp1: Type, tp2: Type) =
+ tp1.deconst.normalize match {
+ case TypeRef(_, sym1, _) if isNumericValueClass(sym1) =>
+ tp2.deconst.normalize match {
+ case TypeRef(_, sym2, _) if isNumericValueClass(sym2) =>
+ isNumericSubClass(sym1, sym2)
+ case tv2 @ TypeVar(_, _) =>
+ tv2.registerBound(tp1, isLowerBound = true, isNumericBound = true)
+ case _ =>
+ isSubType(tp1, tp2)
+ }
+ case tv1 @ TypeVar(_, _) =>
+ tp2.deconst.normalize match {
+ case TypeRef(_, sym2, _) if isNumericValueClass(sym2) =>
+ tv1.registerBound(tp2, isLowerBound = false, isNumericBound = true)
+ case _ =>
+ isSubType(tp1, tp2)
+ }
+ case _ =>
+ isSubType(tp1, tp2)
+ }
+
+ def isNumericSubType(tp1: Type, tp2: Type) =
+ isNumericValueType(tp1) && isNumericValueType(tp2) &&
+ isNumericSubClass(tp1.typeSymbol, tp2.typeSymbol)
+
+ private val lubResults = new mutable.HashMap[(Int, List[Type]), Type]
+ private val glbResults = new mutable.HashMap[(Int, List[Type]), Type]
+
+ def lub(ts: List[Type]): Type = try {
+ lub(ts, lubDepth(ts))
+ } finally {
+ lubResults.clear()
+ glbResults.clear()
+ }
+
+ /** The least upper bound wrt <:< of a list of types */
+ def lub(ts: List[Type], depth: Int): Type = {
+ def lub0(ts0: List[Type]): Type = elimSub(ts0, depth) match {
+ case List() => NothingClass.tpe
+ case List(t) => t
+ case ts @ PolyType(tparams, _) :: _ =>
+ val tparams1 = (tparams, matchingBounds(ts, tparams).transpose).zipped map
+ ((tparam, bounds) => tparam.cloneSymbol.setInfo(glb(bounds, depth)))
+ PolyType(tparams1, lub0(matchingInstTypes(ts, tparams1)))
+ case ts @ MethodType(params, _) :: rest =>
+ MethodType(params, lub0(matchingRestypes(ts, params map (_.tpe))))
+ case ts @ NullaryMethodType(_) :: rest =>
+ NullaryMethodType(lub0(matchingRestypes(ts, Nil)))
+ case ts @ TypeBounds(_, _) :: rest =>
+ TypeBounds(glb(ts map (_.bounds.lo), depth), lub(ts map (_.bounds.hi), depth))
+ case ts =>
+ lubResults get (depth, ts) match {
+ case Some(lubType) =>
+ lubType
+ case None =>
+ lubResults((depth, ts)) = AnyClass.tpe
+ val res = if (depth < 0) AnyClass.tpe else lub1(ts)
+ lubResults((depth, ts)) = res
+ res
+ }
+ }
+ def lub1(ts0: List[Type]): Type = {
+ val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
+ val bts: List[BaseTypeSeq] = ts map (_.baseTypeSeq)
+ val lubBaseTypes: List[Type] = lubBaseTypeSeq(bts, depth)
+ val lubParents = spanningTypes(lubBaseTypes)
+ val lubOwner = commonOwner(ts)
+ val lubBase = intersectionType(lubParents, lubOwner)
+ val lubType =
+ if (phase.erasedTypes || depth == 0) lubBase
+ else {
+ val lubRefined = refinedType(lubParents, lubOwner)
+ val lubThisType = lubRefined.typeSymbol.thisType
+ val narrowts = ts map (_.narrow)
+ def lubsym(proto: Symbol): Symbol = {
+ val prototp = lubThisType.memberInfo(proto)
+ val syms = narrowts map (t =>
+ t.nonPrivateMember(proto.name).suchThat(sym =>
+ sym.tpe matches prototp.substThis(lubThisType.typeSymbol, t)))
+ if (syms contains NoSymbol) NoSymbol
+ else {
+ val symtypes =
+ (narrowts, syms).zipped map ((t, sym) => t.memberInfo(sym).substThis(t.typeSymbol, lubThisType))
+ if (proto.isTerm) // possible problem: owner of info is still the old one, instead of new refinement class
+ proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(lub(symtypes, decr(depth)))
+ else if (symtypes.tail forall (symtypes.head =:=))
+ proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(symtypes.head)
+ else {
+ def lubBounds(bnds: List[TypeBounds]): TypeBounds =
+ TypeBounds(glb(bnds map (_.lo), decr(depth)), lub(bnds map (_.hi), decr(depth)))
+ lubRefined.typeSymbol.newAbstractType(proto.pos, proto.name.toTypeName)
+ .setInfoOwnerAdjusted(lubBounds(symtypes map (_.bounds)))
+ }
+ }
+ }
+ def refines(tp: Type, sym: Symbol): Boolean = {
+ val syms = tp.nonPrivateMember(sym.name).alternatives;
+ !syms.isEmpty && (syms forall (alt =>
+ // todo alt != sym is strictly speaking not correct, but without it we lose
+ // efficiency.
+ alt != sym && !specializesSym(lubThisType, sym, tp, alt)))
+ }
+ for (sym <- lubBase.nonPrivateMembers) {
+ // add a refinement symbol for all non-class members of lubBase
+ // which are refined by every type in ts.
+ if (!sym.isClass && !sym.isConstructor && (narrowts forall (t => refines(t, sym))))
+ try {
+ val lsym = lubsym(sym)
+ if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lubsym(sym))
+ } catch {
+ case ex: NoCommonType =>
+ }
+ }
+ if (lubRefined.decls.isEmpty) lubBase
+ else {
+// println("refined lub of "+ts+"/"+narrowts+" is "+lubRefined+", baseclasses = "+(ts map (_.baseTypeSeq) map (_.toList)))
+ lubRefined
+ }
+ }
+ existentialAbstraction(tparams, lubType)
+ }
+ if (printLubs) {
+ println(indent + "lub of " + ts + " at depth "+depth)//debug
+ indent = indent + " "
+ assert(indent.length <= 100)
+ }
+ val res = lub0(ts)
+ if (printLubs) {
+ indent = indent dropRight 2
+ println(indent + "lub of " + ts + " is " + res)//debug
+ }
+ if (ts forall (_.isNotNull)) res.notNull else res
+ }
+
+ val GlbFailure = new Throwable
+
+ /** A global counter for glb calls in the `specializes' query connected to the `addMembers'
+ * call in `glb'. There's a possible infinite recursion when `specializes' calls
+ * memberType, which calls baseTypeSeq, which calls mergePrefixAndArgs, which calls glb.
+ * The counter breaks this recursion after two calls.
+ * If the recursion is broken, no member is added to the glb.
+ */
+ private var globalGlbDepth = 0
+ private final val globalGlbLimit = 2
+
+ def glb(ts: List[Type]): Type = try {
+ glb(ts, lubDepth(ts))
+ } finally {
+ lubResults.clear()
+ glbResults.clear()
+ }
+
+ /** The greatest lower bound wrt <:< of a list of types */
+ private def glb(ts: List[Type], depth: Int): Type = {
+ def glb0(ts0: List[Type]): Type = elimSuper(ts0) match {
+ case List() => AnyClass.tpe
+ case List(t) => t
+ case ts @ PolyType(tparams, _) :: _ =>
+ val tparams1 = (tparams, matchingBounds(ts, tparams).transpose).zipped map
+ ((tparam, bounds) => tparam.cloneSymbol.setInfo(lub(bounds, depth)))
+ PolyType(tparams1, glb0(matchingInstTypes(ts, tparams1)))
+ case ts @ MethodType(params, _) :: rest =>
+ MethodType(params, glb0(matchingRestypes(ts, params map (_.tpe))))
+ case ts @ NullaryMethodType(_) :: rest =>
+ NullaryMethodType(glb0(matchingRestypes(ts, Nil)))
+ case ts @ TypeBounds(_, _) :: rest =>
+ TypeBounds(lub(ts map (_.bounds.lo), depth), glb(ts map (_.bounds.hi), depth))
+ case ts =>
+ glbResults get (depth, ts) match {
+ case Some(glbType) =>
+ glbType
+ case _ =>
+ glbResults((depth, ts)) = NothingClass.tpe
+ val res = if (depth < 0) NothingClass.tpe else glb1(ts)
+ glbResults((depth, ts)) = res
+ res
+ }
+ }
+ def glb1(ts0: List[Type]): Type = {
+ try {
+ val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
+ val glbOwner = commonOwner(ts)
+ def refinedToParents(t: Type): List[Type] = t match {
+ case RefinedType(ps, _) => ps flatMap refinedToParents
+ case _ => List(t)
+ }
+ def refinedToDecls(t: Type): List[Scope] = t match {
+ case RefinedType(ps, decls) =>
+ val dss = ps flatMap refinedToDecls
+ if (decls.isEmpty) dss else decls :: dss
+ case _ => List()
+ }
+ val ts1 = ts flatMap refinedToParents
+ val glbBase = intersectionType(ts1, glbOwner)
+ val glbType =
+ if (phase.erasedTypes || depth == 0) glbBase
+ else {
+ val glbRefined = refinedType(ts1, glbOwner)
+ val glbThisType = glbRefined.typeSymbol.thisType
+ def glbsym(proto: Symbol): Symbol = {
+ val prototp = glbThisType.memberInfo(proto)
+ val syms = for (t <- ts;
+ alt <- (t.nonPrivateMember(proto.name).alternatives);
+ if glbThisType.memberInfo(alt) matches prototp
+ ) yield alt
+ val symtypes = syms map glbThisType.memberInfo
+ assert(!symtypes.isEmpty)
+ proto.cloneSymbol(glbRefined.typeSymbol).setInfoOwnerAdjusted(
+ if (proto.isTerm) glb(symtypes, decr(depth))
+ else {
+ def isTypeBound(tp: Type) = tp match {
+ case TypeBounds(_, _) => true
+ case _ => false
+ }
+ def glbBounds(bnds: List[Type]): TypeBounds = {
+ val lo = lub(bnds map (_.bounds.lo), decr(depth))
+ val hi = glb(bnds map (_.bounds.hi), decr(depth))
+ if (lo <:< hi) TypeBounds(lo, hi)
+ else throw GlbFailure
+ }
+ val symbounds = symtypes filter isTypeBound
+ var result: Type =
+ if (symbounds.isEmpty)
+ TypeBounds.empty
+ else glbBounds(symbounds)
+ for (t <- symtypes if !isTypeBound(t))
+ if (result.bounds containsType t) result = t
+ else throw GlbFailure
+ result
+ })
+ }
+ if (globalGlbDepth < globalGlbLimit)
+ try {
+ globalGlbDepth += 1
+ val dss = ts flatMap refinedToDecls
+ for (ds <- dss; val sym <- ds.iterator)
+ if (globalGlbDepth < globalGlbLimit && !(glbThisType specializes sym))
+ try {
+ addMember(glbThisType, glbRefined, glbsym(sym))
+ } catch {
+ case ex: NoCommonType =>
+ }
+ } finally {
+ globalGlbDepth -= 1
+ }
+ if (glbRefined.decls.isEmpty) glbBase else glbRefined
+ }
+ existentialAbstraction(tparams, glbType)
+ } catch {
+ case GlbFailure =>
+ if (ts forall (t => NullClass.tpe <:< t)) NullClass.tpe
+ else NothingClass.tpe
+ }
+ }
+ // if (settings.debug.value) { println(indent + "glb of " + ts + " at depth "+depth); indent = indent + " " } //DEBUG
+
+ val res = glb0(ts)
+
+ // if (settings.debug.value) { indent = indent.substring(0, indent.length() - 2); log(indent + "glb of " + ts + " is " + res) }//DEBUG
+
+ if (ts exists (_.isNotNull)) res.notNull else res
+ }
+
+ /** The most deeply nested owner that contains all the symbols
+ * of thistype or prefixless typerefs/singletype occurrences in given type.
+ */
+ private def commonOwner(t: Type): Symbol = {
+ commonOwnerMap.init
+ commonOwnerMap.apply(t)
+ commonOwnerMap.result
+ }
+
+ /** The most deeply nested owner that contains all the symbols
+ * of thistype or prefixless typerefs/singletype occurrences in given list
+ * of types.
+ */
+ private def commonOwner(tps: List[Type]): Symbol = {
+ // if (settings.debug.value) log("computing common owner of types " + tps)//DEBUG
+ commonOwnerMap.init
+ tps foreach { tp => commonOwnerMap.apply(tp); () }
+ commonOwnerMap.result
+ }
+
+ /** Compute lub (if variance == 1) or glb (if variance == -1) of given list
+ * of types `tps'. All types in `tps' are typerefs or singletypes
+ * with the same symbol.
+ * Return `Some(x)' if the computation succeeds with result `x'.
+ * Return `None' if the computation fails.
+ */
+ def mergePrefixAndArgs(tps: List[Type], variance: Int, depth: Int): Option[Type] = tps match {
+ case List(tp) =>
+ Some(tp)
+ case TypeRef(_, sym, _) :: rest =>
+ val pres = tps map (_.prefix) // prefix normalizes automatically
+ val pre = if (variance == 1) lub(pres, depth) else glb(pres, depth)
+ val argss = tps map (_.normalize.typeArgs) // symbol equality (of the tp in tps) was checked using typeSymbol, which normalizes, so should normalize before retrieving arguments
+ val capturedParams = new ListBuffer[Symbol]
+ try {
+ if (sym == ArrayClass && phase.erasedTypes) {
+ // special treatment for lubs of array types after erasure:
+ // if argss contain one value type and some other type, the lub is Object
+ // if argss contain several reference types, the lub is an array over lub of argtypes
+ if (argss exists (_.isEmpty)) {
+ None // something is wrong: an array without a type arg.
+ } else {
+ val args = argss map (_.head)
+ if (args.tail forall (_ =:= args.head)) Some(typeRef(pre, sym, List(args.head)))
+ else if (args exists (arg => isValueClass(arg.typeSymbol))) Some(ObjectClass.tpe)
+ else Some(typeRef(pre, sym, List(lub(args))))
+ }
+ } else {
+ val args = (sym.typeParams, argss.transpose).zipped map {
+ (tparam, as) =>
+ if (depth == 0)
+ if (tparam.variance == variance) AnyClass.tpe
+ else if (tparam.variance == -variance) NothingClass.tpe
+ else NoType
+ else
+ if (tparam.variance == variance) lub(as, decr(depth))
+ else if (tparam.variance == -variance) glb(as, decr(depth))
+ else {
+ val l = lub(as, decr(depth))
+ val g = glb(as, decr(depth))
+ if (l <:< g) l
+ else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we
+ // just err on the conservative side, i.e. with a bound that is too high.
+ // if(!(tparam.info.bounds contains tparam)){ //@M can't deal with f-bounds, see #2251
+
+ val qvar = commonOwner(as) freshExistential "" setInfo TypeBounds(g, l)
+ capturedParams += qvar
+ qvar.tpe
+ }
+ }
+ }
+ if (args contains NoType) None
+ else Some(existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args)))
+ }
+ } catch {
+ case ex: MalformedType => None
+ case ex: IndexOutOfBoundsException => // transpose freaked out because of irregular argss
+ // catching just in case (shouldn't happen, but also doesn't cost us)
+ if (settings.debug.value) log("transposed irregular matrix!?"+ (tps, argss))
+ None
+ }
+ case SingleType(_, sym) :: rest =>
+ val pres = tps map (_.prefix)
+ val pre = if (variance == 1) lub(pres, depth) else glb(pres, depth)
+ try {
+ Some(singleType(pre, sym))
+ } catch {
+ case ex: MalformedType => None
+ }
+ case ExistentialType(tparams, quantified) :: rest =>
+ mergePrefixAndArgs(quantified :: rest, variance, depth) map (existentialAbstraction(tparams, _))
+ case _ =>
+ assert(false, tps); None
+ }
+
+ /** Make symbol `sym' a member of scope `tp.decls'
+ * where `thistp' is the narrowed owner type of the scope.
+ */
+ def addMember(thistp: Type, tp: Type, sym: Symbol) {
+ assert(sym != NoSymbol)
+ // if (settings.debug.value) log("add member " + sym+":"+sym.info+" to "+thistp) //DEBUG
+ if (!(thistp specializes sym)) {
+ if (sym.isTerm)
+ for (alt <- tp.nonPrivateDecl(sym.name).alternatives)
+ if (specializesSym(thistp, sym, thistp, alt))
+ tp.decls unlink alt;
+ tp.decls enter sym
+ }
+ }
+
+ /** All types in list must be polytypes with type parameter lists of
+ * same length as tparams.
+ * Returns list of list of bounds infos, where corresponding type
+ * parameters are renamed to tparams.
+ */
+ private def matchingBounds(tps: List[Type], tparams: List[Symbol]): List[List[Type]] =
+ tps map {
+ case PolyType(tparams1, _) if sameLength(tparams1, tparams) =>
+ tparams1 map (tparam => tparam.info.substSym(tparams1, tparams))
+ case _ =>
+ throw new NoCommonType(tps)
+ }
+
+ /** All types in list must be polytypes with type parameter lists of
+ * same length as tparams.
+ * Returns list of instance types, where corresponding type
+ * parameters are renamed to tparams.
+ */
+ private def matchingInstTypes(tps: List[Type], tparams: List[Symbol]): List[Type] =
+ tps map {
+ case PolyType(tparams1, restpe) if sameLength(tparams1, tparams) =>
+ restpe.substSym(tparams1, tparams)
+ case _ =>
+ throw new NoCommonType(tps)
+ }
+
+ /** All types in list must be method types with equal parameter types.
+ * Returns list of their result types.
+ */
+ private def matchingRestypes(tps: List[Type], pts: List[Type]): List[Type] =
+ tps map {
+ case MethodType(params1, res) if (isSameTypes(params1 map (_.tpe), pts)) =>
+ res
+ case NullaryMethodType(res) if pts isEmpty =>
+ res
+ case _ =>
+ throw new NoCommonType(tps)
+ }
+
+
+// TODO: this desperately needs to be cleaned up
+// plan: split into kind inference and subkinding
+// every Type has a (cached) Kind
+ def kindsConform(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): Boolean = checkKindBounds0(tparams, targs, pre, owner, false).isEmpty
+
+ /** Check well-kindedness of type application (assumes arities are already checked) -- @M
+ *
+ * This check is also performed when abstract type members become concrete (aka a "type alias") -- then tparams.length==1
+ * (checked one type member at a time -- in that case, prefix is the name of the type alias)
+ *
+ * Type application is just like value application: it's "contravariant" in the sense that
+ * the type parameters of the supplied type arguments must conform to the type parameters of
+ * the required type parameters:
+ * - their bounds must be less strict
+ * - variances must match (here, variances are absolute, the variance of a type parameter does not influence the variance of its higher-order parameters)
+ * - @M TODO: are these conditions correct,sufficient&necessary?
+ *
+ * e.g. class Iterable[t, m[+x <: t]] --> the application Iterable[Int, List] is okay, since
+ * List's type parameter is also covariant and its bounds are weaker than <: Int
+ */
+ def checkKindBounds0(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol, explainErrors: Boolean): List[(Type, Symbol, List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)])] = {
+ var error = false
+
+ def transform(tp: Type, clazz: Symbol): Type = tp.asSeenFrom(pre, clazz) // instantiate type params that come from outside the abstract type we're currently checking
+ def transformedBounds(p: Symbol, o: Symbol) = transform(p.info.instantiateTypeParams(tparams, targs).bounds, o)
+
+ /** Check whether <arg>sym1</arg>'s variance conforms to <arg>sym2</arg>'s variance
+ *
+ * If <arg>sym2</arg> is invariant, <arg>sym1</arg>'s variance is irrelevant. Otherwise they must be equal.
+ */
+ def variancesMatch(sym1: Symbol, sym2: Symbol): Boolean = (sym2.variance==0 || sym1.variance==sym2.variance)
+
+ // check that the type parameters <arg>hkargs</arg> to a higher-kinded type conform to the expected params <arg>hkparams</arg>
+ def checkKindBoundsHK(hkargs: List[Symbol], arg: Symbol, param: Symbol, paramowner: Symbol, underHKParams: List[Symbol], withHKArgs: List[Symbol]): (List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)]) = {
+ def bindHKParams(tp: Type) = tp.substSym(underHKParams, withHKArgs)
+ // @M sometimes hkargs != arg.typeParams, the symbol and the type may have very different type parameters
+ val hkparams = param.typeParams
+
+ if (settings.debug.value) {
+ log("checkKindBoundsHK expected: "+ param +" with params "+ hkparams +" by definition in "+ paramowner)
+ log("checkKindBoundsHK supplied: "+ arg +" with params "+ hkargs +" from "+ owner)
+ log("checkKindBoundsHK under params: "+ underHKParams +" with args "+ withHKArgs)
+ }
+
+ if (!sameLength(hkargs, hkparams)) {
+ if(arg == AnyClass || arg == NothingClass) (Nil, Nil, Nil) // Any and Nothing are kind-overloaded
+ else {error = true; (List((arg, param)), Nil, Nil)} // shortcut: always set error, whether explainTypesOrNot
+ } else {
+ val _arityMismatches = if(explainErrors) new ListBuffer[(Symbol, Symbol)] else null
+ val _varianceMismatches = if(explainErrors) new ListBuffer[(Symbol, Symbol)] else null
+ val _stricterBounds = if(explainErrors)new ListBuffer[(Symbol, Symbol)] else null
+ def varianceMismatch(a: Symbol, p: Symbol) { if(explainErrors) _varianceMismatches += ((a, p)) else error = true}
+ def stricterBound(a: Symbol, p: Symbol) { if(explainErrors) _stricterBounds += ((a, p)) else error = true }
+ def arityMismatches(as: Iterable[(Symbol, Symbol)]) { if(explainErrors) _arityMismatches ++= as }
+ def varianceMismatches(as: Iterable[(Symbol, Symbol)]) { if(explainErrors) _varianceMismatches ++= as }
+ def stricterBounds(as: Iterable[(Symbol, Symbol)]) { if(explainErrors) _stricterBounds ++= as }
+
+ for ((hkarg, hkparam) <- hkargs zip hkparams) {
+ if (hkparam.typeParams.isEmpty && hkarg.typeParams.isEmpty) { // base-case: kind *
+ if (!variancesMatch(hkarg, hkparam))
+ varianceMismatch(hkarg, hkparam)
+
+ // instantiateTypeParams(tparams, targs) --> higher-order bounds may contain references to type arguments
+ // substSym(hkparams, hkargs) --> these types are going to be compared as types of kind *
+ // --> their arguments use different symbols, but are conceptually the same
+ // (could also replace the types by polytypes, but can't just strip the symbols, as ordering is lost then)
+ if (!(bindHKParams(transformedBounds(hkparam, paramowner)) <:< transform(hkarg.info.bounds, owner)))
+ stricterBound(hkarg, hkparam)
+
+ if (settings.debug.value) {
+ log("checkKindBoundsHK base case: "+ hkparam +" declared bounds: "+ transformedBounds(hkparam, paramowner) +" after instantiating earlier hkparams: "+ bindHKParams(transformedBounds(hkparam, paramowner)))
+ log("checkKindBoundsHK base case: "+ hkarg +" has bounds: "+ transform(hkarg.info.bounds, owner))
+ }
+ } else {
+ if(settings.debug.value) log("checkKindBoundsHK recursing to compare params of "+ hkparam +" with "+ hkarg)
+ val (am, vm, sb) = checkKindBoundsHK(hkarg.typeParams, hkarg, hkparam, paramowner, underHKParams ++ hkparam.typeParams, withHKArgs ++ hkarg.typeParams)
+ arityMismatches(am)
+ varianceMismatches(vm)
+ stricterBounds(sb)
+ }
+ if(!explainErrors && error) return (Nil, Nil, Nil) // stop as soon as we encountered an error
+ }
+ if(!explainErrors) (Nil, Nil, Nil)
+ else (_arityMismatches.toList, _varianceMismatches.toList, _stricterBounds.toList)
+ }
+ }
+
+ val errors = new ListBuffer[(Type, Symbol, List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)])]
+ (tparams zip targs).foreach{ case (tparam, targ) if (targ.isHigherKinded || !tparam.typeParams.isEmpty) =>
+ // @M must use the typeParams of the type targ, not the typeParams of the symbol of targ!!
+ targ.typeSymbolDirect.info // force symbol load for #4205
+ val tparamsHO = targ.typeParams
+
+ val (arityMismatches, varianceMismatches, stricterBounds) =
+ checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO) // NOTE: *not* targ.typeSymbol, which normalizes
+
+ if(!explainErrors) {if(error) return List((NoType, NoSymbol, Nil, Nil, Nil))}
+ else if (arityMismatches.nonEmpty || varianceMismatches.nonEmpty || stricterBounds.nonEmpty) {
+ errors += ((targ, tparam, arityMismatches, varianceMismatches, stricterBounds))
+ }
+ // case (tparam, targ) => println("no check: "+(tparam, targ, tparam.typeParams.isEmpty))
+ case _ =>
+ }
+
+ errors.toList
+ }
+
+// Errors and Diagnostics -----------------------------------------------------
+
+ /** A throwable signalling a type error */
+ class TypeError(var pos: Position, val msg: String) extends Throwable(msg) {
+ def this(msg: String) = this(NoPosition, msg)
+ }
+
+ class NoCommonType(tps: List[Type]) extends Throwable(
+ "lub/glb of incompatible types: " + tps.mkString("", " and ", "")) with ControlThrowable
+
+ /** A throwable signalling a malformed type */
+ class MalformedType(msg: String) extends TypeError(msg) {
+ def this(pre: Type, tp: String) = this("malformed type: " + pre + "#" + tp)
+ }
+
+ /** An exception signalling a variance annotation/usage conflict */
+ class VarianceError(msg: String) extends TypeError(msg)
+
+ /** The current indentation string for traces */
+ private var indent: String = ""
+
+ /** Perform operation `p' on arguments `tp1',
+ * `arg2' and print trace of computation.
+ */
+ private def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = {
+ Console.println(indent + tp1 + " " + op + " " + arg2 + "?" /* + "("+tp1.getClass+","+arg2.asInstanceOf[AnyRef].getClass+")"*/)
+ indent = indent + " "
+ val result = p(tp1, arg2)
+ indent = indent dropRight 2
+ Console.println(indent + result)
+ result
+ }
+
+ /** If option `explaintypes' is set, print a subtype trace for
+ * `found <:< required'.
+ */
+ def explainTypes(found: Type, required: Type) {
+ if (settings.explaintypes.value) withTypesExplained(found <:< required)
+ }
+
+ /** If option `explaintypes' is set, print a subtype trace for
+ * `op(found, required)'.
+ */
+ def explainTypes(op: (Type, Type) => Any, found: Type, required: Type) {
+ if (settings.explaintypes.value) withTypesExplained(op(found, required))
+ }
+
+ /** Execute `op' while printing a trace of the operations on types executed.
+ */
+ def withTypesExplained[A](op: => A): A = {
+ val s = explainSwitch
+ try { explainSwitch = true; op } finally { explainSwitch = s }
+ }
+
+ def objToAny(tp: Type): Type =
+ if (!phase.erasedTypes && tp.typeSymbol == ObjectClass) AnyClass.tpe
+ else tp
+
+ val shorthands = Set(
+ "scala.collection.immutable.List",
+ "scala.collection.immutable.Nil",
+ "scala.collection.Seq",
+ "scala.collection.Traversable",
+ "scala.collection.Iterable",
+ "scala.collection.mutable.StringBuilder",
+ "scala.collection.IndexedSeq",
+ "scala.collection.Iterator")
+
+
+ /** The maximum number of recursions allowed in toString
+ */
+ final val maxTostringRecursions = 50
+
+ private var tostringRecursions = 0
+}
diff --git a/src/compiler/scala/reflect/common/pickling/UnPickler.scala b/src/compiler/scala/reflect/common/pickling/UnPickler.scala
new file mode 100644
index 0000000000..6b0f933f9b
--- /dev/null
+++ b/src/compiler/scala/reflect/common/pickling/UnPickler.scala
@@ -0,0 +1,841 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package common
+package pickling
+
+import java.io.IOException
+import java.lang.Float.intBitsToFloat
+import java.lang.Double.longBitsToDouble
+
+import Flags._
+import PickleFormat._
+import collection.mutable.{HashMap, ListBuffer}
+import annotation.switch
+
+/** @author Martin Odersky
+ * @version 1.0
+ */
+abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
+ val global: SymbolTable
+ import global._
+
+ /** Unpickle symbol table information descending from a class and/or module root
+ * from an array of bytes.
+ * @param bytes bytearray from which we unpickle
+ * @param offset offset from which unpickling starts
+ * @param classroot the top-level class which is unpickled, or NoSymbol if inapplicable
+ * @param moduleroot the top-level module which is unpickled, or NoSymbol if inapplicable
+ * @param filename filename associated with bytearray, only used for error messages
+ */
+ def unpickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) {
+ try {
+ new Scan(bytes, offset, classRoot, moduleRoot, filename).run()
+ } catch {
+ case ex: IOException =>
+ throw ex
+ case ex: Throwable =>
+ /*if (settings.debug.value)*/ ex.printStackTrace()
+ throw new RuntimeException("error reading Scala signature of "+filename+": "+ex.getMessage())
+ }
+ }
+
+ class Scan(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) extends PickleBuffer(bytes, offset, -1) {
+ //println("unpickle " + classRoot + " and " + moduleRoot)//debug
+
+ protected def debug = settings.debug.value
+
+ checkVersion()
+
+ /** A map from entry numbers to array offsets */
+ private val index = createIndex
+
+ /** A map from entry numbers to symbols, types, or annotations */
+ private val entries = new Array[AnyRef](index.length)
+
+ /** A map from symbols to their associated `decls' scopes */
+ private val symScopes = new HashMap[Symbol, Scope]
+
+ //println("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug
+
+ def run() {
+ // read children last, fix for #3951
+ val queue = new collection.mutable.ListBuffer[() => Unit]()
+ def delay(i: Int, action: => Unit) {
+ queue += (() => at(i, {() => action; null}))
+ }
+
+ for (i <- 0 until index.length) {
+ if (isSymbolEntry(i))
+ at(i, readSymbol)
+ else if (isSymbolAnnotationEntry(i))
+ delay(i, readSymbolAnnotation())
+ else if (isChildrenEntry(i))
+ delay(i, readChildren())
+ }
+
+ for (action <- queue)
+ action()
+ }
+
+ private def checkVersion() {
+ val major = readNat()
+ val minor = readNat()
+ if (major != MajorVersion || minor > MinorVersion)
+ throw new IOException("Scala signature " + classRoot.decodedName +
+ " has wrong version\n expected: " +
+ MajorVersion + "." + MinorVersion +
+ "\n found: " + major + "." + minor +
+ " in "+filename)
+ }
+
+ /** The `decls' scope associated with given symbol */
+ protected def symScope(sym: Symbol) = symScopes.getOrElseUpdate(sym, newScope)
+
+ /** Does entry represent an (internal) symbol */
+ protected def isSymbolEntry(i: Int): Boolean = {
+ val tag = bytes(index(i)).toInt
+ (firstSymTag <= tag && tag <= lastSymTag &&
+ (tag != CLASSsym || !isRefinementSymbolEntry(i)))
+ }
+
+ /** Does entry represent an (internal or external) symbol */
+ protected def isSymbolRef(i: Int): Boolean = {
+ val tag = bytes(index(i))
+ (firstSymTag <= tag && tag <= lastExtSymTag)
+ }
+
+ /** Does entry represent a name? */
+ protected def isNameEntry(i: Int): Boolean = {
+ val tag = bytes(index(i)).toInt
+ tag == TERMname || tag == TYPEname
+ }
+
+ /** Does entry represent a symbol annotation? */
+ protected def isSymbolAnnotationEntry(i: Int): Boolean = {
+ val tag = bytes(index(i)).toInt
+ tag == SYMANNOT
+ }
+
+ /** Does the entry represent children of a symbol? */
+ protected def isChildrenEntry(i: Int): Boolean = {
+ val tag = bytes(index(i)).toInt
+ tag == CHILDREN
+ }
+
+ /** Does entry represent a refinement symbol?
+ * pre: Entry is a class symbol
+ */
+ protected def isRefinementSymbolEntry(i: Int): Boolean = {
+ val savedIndex = readIndex
+ readIndex = index(i)
+ val tag = readByte().toInt
+ assert(tag == CLASSsym)
+
+ readNat(); // read length
+ val result = readNameRef() == tpnme.REFINE_CLASS_NAME
+ readIndex = savedIndex
+ result
+ }
+
+ /** If entry at <code>i</code> is undefined, define it by performing
+ * operation <code>op</code> with <code>readIndex at start of i'th
+ * entry. Restore <code>readIndex</code> afterwards.
+ */
+ protected def at[T <: AnyRef](i: Int, op: () => T): T = {
+ var r = entries(i)
+ if (r eq null) {
+ val savedIndex = readIndex
+ readIndex = index(i)
+ r = op()
+ assert(entries(i) eq null, entries(i))
+ entries(i) = r
+ readIndex = savedIndex
+ }
+ r.asInstanceOf[T]
+ }
+
+ /** Read a name */
+ protected def readName(): Name = {
+ val tag = readByte()
+ val len = readNat()
+ tag match {
+ case TERMname => newTermName(bytes, readIndex, len)
+ case TYPEname => newTypeName(bytes, readIndex, len)
+ case _ => errorBadSignature("bad name tag: " + tag)
+ }
+ }
+
+ /** Read a symbol */
+ protected def readSymbol(): Symbol = {
+ val tag = readByte()
+ val end = readNat() + readIndex
+ def atEnd = readIndex == end
+
+ def readExtSymbol(): Symbol = {
+ val name = readNameRef()
+ val owner = if (atEnd) definitions.RootClass else readSymbolRef()
+
+ def fromName(name: Name) = mkTermName(name) match {
+ case nme.ROOT => definitions.RootClass
+ case nme.ROOTPKG => definitions.RootPackage
+ case _ =>
+ val s = owner.info.decl(name)
+ if (tag == EXTref) s else s.moduleClass
+ }
+ def nestedObjectSymbol: Symbol = {
+ // If the owner is overloaded (i.e. a method), it's not possible to select the
+ // right member, so return NoSymbol. This can only happen when unpickling a tree.
+ // the "case Apply" in readTree() takes care of selecting the correct alternative
+ // after parsing the arguments.
+ if (owner.isOverloaded)
+ return NoSymbol
+
+ if (tag == EXTMODCLASSref) {
+ val moduleVar = owner.info.decl(nme.moduleVarName(name))
+ if (moduleVar.isLazyAccessor)
+ return moduleVar.lazyAccessor.lazyAccessor
+ }
+ NoSymbol
+ }
+
+ // (1) Try name.
+ fromName(name) orElse {
+ // (2) Try with expanded name. Can happen if references to private
+ // symbols are read from outside: for instance when checking the children
+ // of a class. See #1722.
+ fromName(nme.expandedName(name, owner)) orElse {
+ // (3) Try as a nested object symbol.
+ nestedObjectSymbol orElse {
+ // (4) Otherwise, fail.
+ errorMissingRequirement(name, owner)
+ }
+ }
+ }
+ }
+
+ tag match {
+ case NONEsym => return NoSymbol
+ case EXTref | EXTMODCLASSref => return readExtSymbol()
+ case _ => ()
+ }
+
+ // symbols that were pickled with Pickler.writeSymInfo
+ val nameref = readNat()
+ val name = at(nameref, readName)
+ val owner = readSymbolRef()
+ val flags = pickledToRawFlags(readLongNat())
+ var inforef = readNat()
+ val privateWithin =
+ if (!isSymbolRef(inforef)) NoSymbol
+ else {
+ val pw = at(inforef, readSymbol)
+ inforef = readNat()
+ pw
+ }
+
+ def isModuleFlag = (flags & MODULE) != 0L
+ def isMethodFlag = (flags & METHOD) != 0L
+ def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner)
+ def isModuleRoot = (name == moduleRoot.name) && (owner == moduleRoot.owner)
+
+ def finishSym(sym: Symbol): Symbol = {
+ sym.flags = flags & PickledFlags
+ sym.privateWithin = privateWithin
+ sym.info = (
+ if (atEnd) {
+ assert(!sym.isSuperAccessor, sym)
+ newLazyTypeRef(inforef)
+ }
+ else {
+ assert(sym.isSuperAccessor || sym.isParamAccessor, sym)
+ newLazyTypeRefAndAlias(inforef, readNat())
+ }
+ )
+ if (sym.owner.isClass && sym != classRoot && sym != moduleRoot &&
+ !sym.isModuleClass && !sym.isRefinementClass && !sym.isTypeParameter && !sym.isExistentiallyBound)
+ symScope(sym.owner) enter sym
+
+ sym
+ }
+
+ finishSym(tag match {
+ case TYPEsym => owner.newAbstractType(mkTypeName(name))
+ case ALIASsym => owner.newAliasType(mkTypeName(name))
+ case CLASSsym =>
+ val sym = (isClassRoot, isModuleFlag) match {
+ case (true, true) => moduleRoot.moduleClass
+ case (true, false) => classRoot
+ case (false, true) => owner.newModuleClass(mkTypeName(name))
+ case (false, false) => owner.newClass(mkTypeName(name))
+ }
+ if (!atEnd)
+ sym.typeOfThis = newLazyTypeRef(readNat())
+
+ sym
+ case MODULEsym =>
+ val clazz = at(inforef, () => readType()).typeSymbol // after the NMT_TRANSITION period, we can leave off the () => ... ()
+ if (isModuleRoot) moduleRoot
+ else {
+ val m = owner.newModule(name, clazz)
+ clazz.sourceModule = m
+ m
+ }
+ case VALsym =>
+ if (isModuleRoot) { assert(false); NoSymbol }
+ else if (isMethodFlag) owner.newMethod(name)
+ else owner.newValue(name)
+
+ case _ =>
+ errorBadSignature("bad symbol tag: " + tag)
+ })
+ }
+
+ /** Read a type
+ *
+ * @param forceProperType is used to ease the transition to NullaryMethodTypes (commentmarker: NMT_TRANSITION)
+ * the flag say that a type of kind * is expected, so that PolyType(tps, restpe) can be disambiguated to PolyType(tps, NullaryMethodType(restpe))
+ * (if restpe is not a ClassInfoType, a MethodType or a NullaryMethodType, which leaves TypeRef/SingletonType -- the latter would make the polytype a type constructor)
+ */
+ protected def readType(forceProperType: Boolean = false): Type = {
+ val tag = readByte()
+ val end = readNat() + readIndex
+ (tag: @switch) match {
+ case NOtpe =>
+ NoType
+ case NOPREFIXtpe =>
+ NoPrefix
+ case THIStpe =>
+ ThisType(readSymbolRef())
+ case SINGLEtpe =>
+ SingleType(readTypeRef(), readSymbolRef()) // !!! was singleType
+ case SUPERtpe =>
+ val thistpe = readTypeRef()
+ val supertpe = readTypeRef()
+ SuperType(thistpe, supertpe)
+ case CONSTANTtpe =>
+ ConstantType(readConstantRef())
+ case TYPEREFtpe =>
+ val pre = readTypeRef()
+ val sym = readSymbolRef()
+ var args = until(end, readTypeRef)
+ TypeRef(pre, sym, args)
+ case TYPEBOUNDStpe =>
+ TypeBounds(readTypeRef(), readTypeRef())
+ case REFINEDtpe =>
+ val clazz = readSymbolRef()
+ RefinedType(until(end, readTypeRef), symScope(clazz), clazz)
+ case CLASSINFOtpe =>
+ val clazz = readSymbolRef()
+ ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz)
+ case METHODtpe | IMPLICITMETHODtpe =>
+ val restpe = readTypeRef()
+ val params = until(end, readSymbolRef)
+ // if the method is overloaded, the params cannot be determined (see readSymbol) => return NoType.
+ // Only happen for trees, "case Apply" in readTree() takes care of selecting the correct
+ // alternative after parsing the arguments.
+ if (params.contains(NoSymbol) || restpe == NoType) NoType
+ else MethodType(params, restpe)
+ case POLYtpe =>
+ val restpe = readTypeRef()
+ val typeParams = until(end, readSymbolRef)
+ if(typeParams nonEmpty) {
+ // NMT_TRANSITION: old class files denoted a polymorphic nullary method as PolyType(tps, restpe), we now require PolyType(tps, NullaryMethodType(restpe))
+ // when a type of kind * is expected (forceProperType is true), we know restpe should be wrapped in a NullaryMethodType (if it wasn't suitably wrapped yet)
+ def transitionNMT(restpe: Type) = {
+ val resTpeCls = restpe.getClass.toString // what's uglier than isInstanceOf? right! -- isInstanceOf does not work since the concrete types are defined in the compiler (not in scope here)
+ if(forceProperType /*&& pickleformat < 2.9 */ && !(resTpeCls.endsWith("MethodType"))) { assert(!resTpeCls.contains("ClassInfoType"))
+ NullaryMethodType(restpe) }
+ else restpe
+ }
+ PolyType(typeParams, transitionNMT(restpe))
+ }
+ else
+ NullaryMethodType(restpe)
+ case EXISTENTIALtpe =>
+ val restpe = readTypeRef()
+ ExistentialType(until(end, readSymbolRef), restpe)
+ case ANNOTATEDtpe =>
+ var typeRef = readNat()
+ val selfsym = if (isSymbolRef(typeRef)) {
+ val s = at(typeRef, readSymbol)
+ typeRef = readNat()
+ s
+ } else NoSymbol // selfsym can go.
+ val tp = at(typeRef, () => readType(forceProperType)) // NMT_TRANSITION
+ val annots = until(end, readAnnotationRef)
+ if (selfsym == NoSymbol) AnnotatedType(annots, tp, selfsym)
+ else tp
+ case _ =>
+ noSuchTypeTag(tag, end)
+ }
+ }
+
+ def noSuchTypeTag(tag: Int, end: Int): Type =
+ errorBadSignature("bad type tag: " + tag)
+
+ /** Read a constant */
+ protected def readConstant(): Constant = {
+ val tag = readByte().toInt
+ val len = readNat()
+ (tag: @switch) match {
+ case LITERALunit => Constant(())
+ case LITERALboolean => Constant(readLong(len) != 0L)
+ case LITERALbyte => Constant(readLong(len).toByte)
+ case LITERALshort => Constant(readLong(len).toShort)
+ case LITERALchar => Constant(readLong(len).toChar)
+ case LITERALint => Constant(readLong(len).toInt)
+ case LITERALlong => Constant(readLong(len))
+ case LITERALfloat => Constant(intBitsToFloat(readLong(len).toInt))
+ case LITERALdouble => Constant(longBitsToDouble(readLong(len)))
+ case LITERALstring => Constant(readNameRef().toString())
+ case LITERALnull => Constant(null)
+ case LITERALclass => Constant(readTypeRef())
+ case LITERALenum => Constant(readSymbolRef())
+ case _ => noSuchConstantTag(tag, len)
+ }
+ }
+
+ def noSuchConstantTag(tag: Int, len: Int): Constant =
+ errorBadSignature("bad constant tag: " + tag)
+
+ /** Read children and store them into the corresponding symbol.
+ */
+ protected def readChildren() {
+ val tag = readByte()
+ assert(tag == CHILDREN)
+ val end = readNat() + readIndex
+ val target = readSymbolRef()
+ while (readIndex != end) target addChild readSymbolRef()
+ }
+
+ /** Read an annotation argument, which is pickled either
+ * as a Constant or a Tree.
+ */
+ protected def readAnnotArg(i: Int): Tree = bytes(index(i)) match {
+ case TREE => at(i, readTree)
+ case _ =>
+ val const = at(i, readConstant)
+ Literal(const) setType const.tpe
+ }
+
+ /** Read a ClassfileAnnotArg (argument to a classfile annotation)
+ */
+ private def readArrayAnnot() = {
+ readByte() // skip the `annotargarray` tag
+ val end = readNat() + readIndex
+ until(end, () => readClassfileAnnotArg(readNat())).toArray(classfileAnnotArgManifest)
+ }
+ protected def readClassfileAnnotArg(i: Int): ClassfileAnnotArg = bytes(index(i)) match {
+ case ANNOTINFO => NestedAnnotArg(at(i, readAnnotation))
+ case ANNOTARGARRAY => at(i, () => ArrayAnnotArg(readArrayAnnot()))
+ case _ => LiteralAnnotArg(at(i, readConstant))
+ }
+
+ /** Read an AnnotationInfo. Not to be called directly, use
+ * readAnnotation or readSymbolAnnotation
+ */
+ protected def readAnnotationInfo(end: Int): AnnotationInfo = {
+ val atp = readTypeRef()
+ val args = new ListBuffer[Tree]
+ val assocs = new ListBuffer[(Name, ClassfileAnnotArg)]
+ while (readIndex != end) {
+ val argref = readNat()
+ if (isNameEntry(argref)) {
+ val name = at(argref, readName)
+ val arg = readClassfileAnnotArg(readNat())
+ assocs += ((name, arg))
+ }
+ else
+ args += readAnnotArg(argref)
+ }
+ AnnotationInfo(atp, args.toList, assocs.toList)
+ }
+
+ /** Read an annotation and as a side effect store it into
+ * the symbol it requests. Called at top-level, for all
+ * (symbol, annotInfo) entries. */
+ protected def readSymbolAnnotation() {
+ val tag = readByte()
+ if (tag != SYMANNOT)
+ errorBadSignature("symbol annotation expected ("+ tag +")")
+ val end = readNat() + readIndex
+ val target = readSymbolRef()
+ target.addAnnotation(readAnnotationInfo(end))
+ }
+
+ /** Read an annotation and return it. Used when unpickling
+ * an ANNOTATED(WSELF)tpe or a NestedAnnotArg */
+ protected def readAnnotation(): AnnotationInfo = {
+ val tag = readByte()
+ if (tag != ANNOTINFO)
+ errorBadSignature("annotation expected (" + tag + ")")
+ val end = readNat() + readIndex
+ readAnnotationInfo(end)
+ }
+
+ /* Read an abstract syntax tree */
+ protected def readTree(): Tree = {
+ val outerTag = readByte()
+ if (outerTag != TREE)
+ errorBadSignature("tree expected (" + outerTag + ")")
+ val end = readNat() + readIndex
+ val tag = readByte()
+ val tpe = if (tag == EMPTYtree) NoType else readTypeRef()
+
+ // Set by the three functions to follow. If symbol is non-null
+ // after the the new tree 't' has been created, t has its Symbol
+ // set to symbol; and it always has its Type set to tpe.
+ var symbol: Symbol = null
+ var mods: Modifiers = null
+ var name: Name = null
+
+ /** Read a Symbol, Modifiers, and a Name */
+ def setSymModsName() {
+ symbol = readSymbolRef()
+ mods = readModifiersRef()
+ name = readNameRef()
+ }
+ /** Read a Symbol and a Name */
+ def setSymName() {
+ symbol = readSymbolRef()
+ name = readNameRef()
+ }
+ /** Read a Symbol */
+ def setSym() {
+ symbol = readSymbolRef()
+ }
+
+ val t = tag match {
+ case EMPTYtree =>
+ EmptyTree
+
+ case PACKAGEtree =>
+ setSym()
+ val pid = readTreeRef().asInstanceOf[RefTree]
+ val stats = until(end, readTreeRef)
+ PackageDef(pid, stats)
+
+ case CLASStree =>
+ setSymModsName()
+ val impl = readTemplateRef()
+ val tparams = until(end, readTypeDefRef)
+ ClassDef(mods, mkTypeName(name), tparams, impl)
+
+ case MODULEtree =>
+ setSymModsName()
+ ModuleDef(mods, name, readTemplateRef())
+
+ case VALDEFtree =>
+ setSymModsName()
+ val tpt = readTreeRef()
+ val rhs = readTreeRef()
+ ValDef(mods, name, tpt, rhs)
+
+ case DEFDEFtree =>
+ setSymModsName()
+ val tparams = times(readNat(), readTypeDefRef)
+ val vparamss = times(readNat(), () => times(readNat(), readValDefRef))
+ val tpt = readTreeRef()
+ val rhs = readTreeRef()
+ DefDef(mods, name, tparams, vparamss, tpt, rhs)
+
+ case TYPEDEFtree =>
+ setSymModsName()
+ val rhs = readTreeRef()
+ val tparams = until(end, readTypeDefRef)
+ TypeDef(mods, mkTypeName(name), tparams, rhs)
+
+ case LABELtree =>
+ setSymName()
+ val rhs = readTreeRef()
+ val params = until(end, readIdentRef)
+ LabelDef(name, params, rhs)
+
+ case IMPORTtree =>
+ setSym()
+ val expr = readTreeRef()
+ val selectors = until(end, () => {
+ val from = readNameRef()
+ val to = readNameRef()
+ ImportSelector(from, -1, to, -1)
+ })
+
+ Import(expr, selectors)
+
+ case TEMPLATEtree =>
+ setSym()
+ val parents = times(readNat(), readTreeRef)
+ val self = readValDefRef()
+ val body = until(end, readTreeRef)
+
+ Template(parents, self, body)
+
+ case BLOCKtree =>
+ val expr = readTreeRef()
+ val stats = until(end, readTreeRef)
+ Block(stats, expr)
+
+ case CASEtree =>
+ val pat = readTreeRef()
+ val guard = readTreeRef()
+ val body = readTreeRef()
+ CaseDef(pat, guard, body)
+
+ case ALTERNATIVEtree =>
+ Alternative(until(end, readTreeRef))
+
+ case STARtree =>
+ Star(readTreeRef())
+
+ case BINDtree =>
+ setSymName()
+ Bind(name, readTreeRef())
+
+ case UNAPPLYtree =>
+ val fun = readTreeRef()
+ val args = until(end, readTreeRef)
+ UnApply(fun, args)
+
+ case ARRAYVALUEtree =>
+ val elemtpt = readTreeRef()
+ val trees = until(end, readTreeRef)
+ ArrayValue(elemtpt, trees)
+
+ case FUNCTIONtree =>
+ setSym()
+ val body = readTreeRef()
+ val vparams = until(end, readValDefRef)
+ Function(vparams, body)
+
+ case ASSIGNtree =>
+ val lhs = readTreeRef()
+ val rhs = readTreeRef()
+ Assign(lhs, rhs)
+
+ case IFtree =>
+ val cond = readTreeRef()
+ val thenp = readTreeRef()
+ val elsep = readTreeRef()
+ If(cond, thenp, elsep)
+
+ case MATCHtree =>
+ val selector = readTreeRef()
+ val cases = until(end, readCaseDefRef)
+ Match(selector, cases)
+
+ case RETURNtree =>
+ setSym()
+ Return(readTreeRef())
+
+ case TREtree =>
+ val block = readTreeRef()
+ val finalizer = readTreeRef()
+ val catches = until(end, readCaseDefRef)
+ Try(block, catches, finalizer)
+
+ case THROWtree =>
+ Throw(readTreeRef())
+
+ case NEWtree =>
+ New(readTreeRef())
+
+ case TYPEDtree =>
+ val expr = readTreeRef()
+ val tpt = readTreeRef()
+ Typed(expr, tpt)
+
+ case TYPEAPPLYtree =>
+ val fun = readTreeRef()
+ val args = until(end, readTreeRef)
+ TypeApply(fun, args)
+
+ case APPLYtree =>
+ val fun = readTreeRef()
+ val args = until(end, readTreeRef)
+ if (fun.symbol.isOverloaded) {
+ fun.setType(fun.symbol.info)
+ inferMethodAlternative(fun, args map (_.tpe), tpe)
+ }
+ Apply(fun, args)
+
+ case APPLYDYNAMICtree =>
+ setSym()
+ val qual = readTreeRef()
+ val args = until(end, readTreeRef)
+ ApplyDynamic(qual, args)
+
+ case SUPERtree =>
+ setSym()
+ val qual = readTreeRef()
+ val mix = readTypeNameRef()
+ Super(qual, mix)
+
+ case THIStree =>
+ setSym()
+ This(readTypeNameRef())
+
+ case SELECTtree =>
+ setSym()
+ val qualifier = readTreeRef()
+ val selector = readNameRef()
+ Select(qualifier, selector)
+
+ case IDENTtree =>
+ setSymName()
+ Ident(name)
+
+ case LITERALtree =>
+ Literal(readConstantRef())
+
+ case TYPEtree =>
+ TypeTree()
+
+ case ANNOTATEDtree =>
+ val annot = readTreeRef()
+ val arg = readTreeRef()
+ Annotated(annot, arg)
+
+ case SINGLETONTYPEtree =>
+ SingletonTypeTree(readTreeRef())
+
+ case SELECTFROMTYPEtree =>
+ val qualifier = readTreeRef()
+ val selector = readTypeNameRef()
+ SelectFromTypeTree(qualifier, selector)
+
+ case COMPOUNDTYPEtree =>
+ CompoundTypeTree(readTemplateRef())
+
+ case APPLIEDTYPEtree =>
+ val tpt = readTreeRef()
+ val args = until(end, readTreeRef)
+ AppliedTypeTree(tpt, args)
+
+ case TYPEBOUNDStree =>
+ val lo = readTreeRef()
+ val hi = readTreeRef()
+ TypeBoundsTree(lo, hi)
+
+ case EXISTENTIALTYPEtree =>
+ val tpt = readTreeRef()
+ val whereClauses = until(end, readTreeRef)
+ ExistentialTypeTree(tpt, whereClauses)
+
+ case _ =>
+ noSuchTreeTag(tag, end)
+ }
+
+ if (symbol == null) t setType tpe
+ else t setSymbol symbol setType tpe
+ }
+
+ def noSuchTreeTag(tag: Int, end: Int) =
+ errorBadSignature("unknown tree type (" + tag + ")")
+
+ def readModifiers(): Modifiers = {
+ val tag = readNat()
+ if (tag != MODIFIERS)
+ errorBadSignature("expected a modifiers tag (" + tag + ")")
+ val end = readNat() + readIndex
+ val pflagsHi = readNat()
+ val pflagsLo = readNat()
+ val pflags = (pflagsHi.toLong << 32) + pflagsLo
+ val flags = pickledToRawFlags(pflags)
+ val privateWithin = readNameRef()
+ Modifiers(flags, privateWithin, Nil, Map.empty)
+ }
+
+ /* Read a reference to a pickled item */
+ protected def readNameRef(): Name = at(readNat(), readName)
+ protected def readSymbolRef(): Symbol = at(readNat(), readSymbol)
+ protected def readTypeRef(): Type = at(readNat(), () => readType()) // after the NMT_TRANSITION period, we can leave off the () => ... ()
+ protected def readConstantRef(): Constant = at(readNat(), readConstant)
+ protected def readAnnotationRef(): AnnotationInfo = at(readNat(), readAnnotation)
+ protected def readModifiersRef(): Modifiers = at(readNat(), readModifiers)
+ protected def readTreeRef(): Tree = at(readNat(), readTree)
+
+ protected def readTypeNameRef(): TypeName = mkTypeName(readNameRef())
+ protected def readTermNameRef(): TermName = mkTermName(readNameRef())
+
+ protected def readTemplateRef(): Template =
+ readTreeRef() match {
+ case templ:Template => templ
+ case other =>
+ errorBadSignature("expected a template (" + other + ")")
+ }
+ protected def readCaseDefRef(): CaseDef =
+ readTreeRef() match {
+ case tree:CaseDef => tree
+ case other =>
+ errorBadSignature("expected a case def (" + other + ")")
+ }
+ protected def readValDefRef(): ValDef =
+ readTreeRef() match {
+ case tree:ValDef => tree
+ case other =>
+ errorBadSignature("expected a ValDef (" + other + ")")
+ }
+ protected def readIdentRef(): Ident =
+ readTreeRef() match {
+ case tree:Ident => tree
+ case other =>
+ errorBadSignature("expected an Ident (" + other + ")")
+ }
+ protected def readTypeDefRef(): TypeDef =
+ readTreeRef() match {
+ case tree:TypeDef => tree
+ case other =>
+ errorBadSignature("expected an TypeDef (" + other + ")")
+ }
+
+ protected def errorBadSignature(msg: String) =
+ throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg)
+
+ protected def errorMissingRequirement(msg: String): Nothing =
+ if (debug) errorBadSignature(msg)
+ else throw new IOException("class file needed by "+classRoot.name+" is missing.\n"+msg)
+
+ protected def errorMissingRequirement(name: Name, owner: Symbol): Nothing =
+ errorMissingRequirement(
+ "reference " + (if (name.isTypeName) "type " else "value ") +
+ name.decode + " of " + owner.tpe.widen + " refers to nonexisting symbol.")
+
+ def inferMethodAlternative(fun: Tree, argtpes: List[Type], restpe: Type) {} // can't do it; need a compiler for that.
+
+ def newLazyTypeRef(i: Int): LazyType = new LazyTypeRef(i)
+ def newLazyTypeRefAndAlias(i: Int, j: Int): LazyType = new LazyTypeRefAndAlias(i, j)
+
+ /** A lazy type which when completed returns type at index `i`. */
+ private class LazyTypeRef(i: Int) extends LazyType {
+ private val definedAtRunId = currentRunId
+ private val p = phase
+ override def complete(sym: Symbol) : Unit = {
+ val tp = at(i, () => readType(sym.isTerm)) // after NMT_TRANSITION, revert `() => readType(sym.isTerm)` to `readType`
+ if (p != phase) atPhase(p) (sym setInfo tp)
+ else sym setInfo tp
+ if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp))
+ }
+ override def load(sym: Symbol) { complete(sym) }
+ }
+
+ /** A lazy type which when completed returns type at index `i` and sets alias
+ * of completed symbol to symbol at index `j`.
+ */
+ private class LazyTypeRefAndAlias(i: Int, j: Int) extends LazyTypeRef(i) {
+ override def complete(sym: Symbol) {
+ super.complete(sym)
+ var alias = at(j, readSymbol)
+ if (alias.isOverloaded) {
+ atPhase(picklerPhase) {
+ alias = alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt))
+ }
+ }
+ sym.asInstanceOf[TermSymbol].setAlias(alias)
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/reflect/common/util/Chars.scala b/src/compiler/scala/reflect/common/util/Chars.scala
deleted file mode 100644
index 4175455f1f..0000000000
--- a/src/compiler/scala/reflect/common/util/Chars.scala
+++ /dev/null
@@ -1,92 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2006-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-package scala.reflect.common.util
-
-import annotation.{ tailrec, switch }
-import java.lang.{ Character => JCharacter }
-
-/** Contains constants and classifier methods for characters */
-trait Chars {
- // Be very careful touching these.
- // Apparently trivial changes to the way you write these constants
- // will cause Scanners.scala to go from a nice efficient switch to
- // a ghastly nested if statement which will bring the type checker
- // to its knees. See ticket #1456
- // Martin: (this should be verified now that the pattern rules have been redesigned).
- final val LF = '\u000A'
- final val FF = '\u000C'
- final val CR = '\u000D'
- final val SU = '\u001A'
-
- /** Convert a character digit to an Int according to given base,
- * -1 if no success */
- def digit2int(ch: Char, base: Int): Int = {
- if ('0' <= ch && ch <= '9' && ch < '0' + base)
- ch - '0'
- else if ('A' <= ch && ch < 'A' + base - 10)
- ch - 'A' + 10
- else if ('a' <= ch && ch < 'a' + base - 10)
- ch - 'a' + 10
- else
- -1
- }
-
- /** Convert a character to a backslash-u escape */
- def char2uescape(c: Char): String = {
- var rest = c.toInt
- val buf = new StringBuilder
- for (i <- 1 to 4) {
- buf ++= (rest % 16).toHexString
- rest = rest / 16
- }
- "\\u" + buf.toString.reverse
- }
-
- /** Is character a line break? */
- @inline def isLineBreakChar(c: Char) = (c: @switch) match {
- case LF|FF|CR|SU => true
- case _ => false
- }
-
- /** Is character a whitespace character (but not a new line)? */
- def isWhitespace(c: Char) =
- c == ' ' || c == '\t' || c == CR
-
- /** Can character form part of a doc comment variable $xxx? */
- def isVarPart(c: Char) =
- '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
-
- /** Can character start an alphanumeric Scala identifier? */
- def isIdentifierStart(c: Char): Boolean =
- (c == '_') || (c == '$') || Character.isUnicodeIdentifierStart(c)
-
- /** Can character form part of an alphanumeric Scala identifier? */
- def isIdentifierPart(c: Char) =
- (c == '$') || Character.isUnicodeIdentifierPart(c)
-
- /** Is character a math or other symbol in Unicode? */
- def isSpecial(c: Char) = {
- val chtp = Character.getType(c)
- chtp == Character.MATH_SYMBOL.toInt || chtp == Character.OTHER_SYMBOL.toInt
- }
-
- private final val otherLetters = Set[Char]('\u0024', '\u005F') // '$' and '_'
- private final val letterGroups = {
- import JCharacter._
- Set[Byte](LOWERCASE_LETTER, UPPERCASE_LETTER, OTHER_LETTER, TITLECASE_LETTER, LETTER_NUMBER)
- }
- def isScalaLetter(ch: Char) = letterGroups(JCharacter.getType(ch).toByte) || otherLetters(ch)
-
- /** Can character form part of a Scala operator name? */
- def isOperatorPart(c : Char) : Boolean = (c: @switch) match {
- case '~' | '!' | '@' | '#' | '%' |
- '^' | '*' | '+' | '-' | '<' |
- '>' | '?' | ':' | '=' | '&' |
- '|' | '/' | '\\' => true
- case c => isSpecial(c)
- }
-}
-
-object Chars extends Chars { }
diff --git a/src/compiler/scala/reflect/std/JavaMappings.scala b/src/compiler/scala/reflect/std/JavaMappings.scala
new file mode 100644
index 0000000000..606972420d
--- /dev/null
+++ b/src/compiler/scala/reflect/std/JavaMappings.scala
@@ -0,0 +1,62 @@
+package scala.reflect
+package std
+
+import common._
+import collection.mutable.ListBuffer
+
+trait JavaMappings { self: Mirror =>
+
+ import definitions._
+
+ type TypeParamMap = Map[java.lang.reflect.TypeVariable[_], Symbol]
+
+ private val localDummy = definitions.RootClass.newValue(NoPosition, "<local-dummy>").setFlag(Flags.SYNTHETIC).setInfo(NoType)
+
+ def fromJava(clazz: java.lang.Class[_]): Symbol = clazz match {
+ case java.lang.Boolean.TYPE => BooleanClass
+ case java.lang.Character.TYPE => CharClass
+ case java.lang.Byte.TYPE => ByteClass
+ case java.lang.Short.TYPE => ShortClass
+ case java.lang.Integer.TYPE => IntClass
+ case java.lang.Long.TYPE => LongClass
+ case java.lang.Float.TYPE => FloatClass
+ case java.lang.Double.TYPE => DoubleClass
+ case java.lang.Void.TYPE => UnitClass
+ case _ => definitions.getClass(clazz.getName)
+ }
+
+ def fromJavaType(jtpe: java.lang.reflect.Type)(implicit tparMap: TypeParamMap): Type = jtpe match {
+ case clazz: java.lang.Class[_] =>
+ if (clazz.isArray) arrayType(fromJavaType(clazz.getComponentType))
+ else {
+ val sym = fromJava(clazz)
+ if (clazz.isLocalClass) typeRef(NoPrefix, sym, List())
+ else if (clazz.isMemberClass) typeRef(fromJavaType(clazz.getDeclaringClass), sym, List())
+ else sym.tpe
+ }
+ case ptpe: java.lang.reflect.ParameterizedType =>
+ val TypeRef(pre0, sym, _) = fromJavaType(ptpe.getRawType)
+ val jpre = ptpe.getOwnerType
+ val pre = if (jpre != null) fromJavaType(jpre) else pre0
+ val exbuf = new ListBuffer[Symbol]
+ def fromJavaArgType(jtp: java.lang.reflect.Type) = fromJavaType(jtp) match {
+ case BoundedWildcardType(bounds) =>
+ val tparam = pre.typeSymbol.newTypeParameter(NoPosition, newTypeName("x$" + exbuf.length)).setInfo(bounds)
+ exbuf += tparam
+ tparam.tpe
+ case tp => tp
+ }
+ val args = ptpe.getActualTypeArguments.toList map fromJavaArgType
+ existentialAbstraction(exbuf.toList, typeRef(pre, sym, args))
+ case gtpe: java.lang.reflect.GenericArrayType =>
+ val etpe = fromJavaType(gtpe.getGenericComponentType)
+ arrayType(etpe)
+ case wtpe: java.lang.reflect.WildcardType =>
+ BoundedWildcardType(
+ TypeBounds(
+ (wtpe.getLowerBounds map fromJavaType).headOption getOrElse NothingClass.tpe,
+ intersectionType((wtpe.getUpperBounds map fromJavaType).toList)))
+ case vtpe: java.lang.reflect.TypeVariable[_] =>
+ tparMap(vtpe).tpe
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/std/Mirror.scala b/src/compiler/scala/reflect/std/Mirror.scala
new file mode 100644
index 0000000000..69ddfa1e71
--- /dev/null
+++ b/src/compiler/scala/reflect/std/Mirror.scala
@@ -0,0 +1,14 @@
+package scala.reflect
+package std
+
+import common._
+
+abstract class Mirror extends SymbolTable
+ with JavaMappings
+ with SymbolCompleters
+ with Positions { self =>
+
+ val unpickler = new common.pickling.UnPickler { val global: self.type = self }
+ override val settings = new ReflectSettings
+
+}
diff --git a/src/compiler/scala/reflect/std/Positions.scala b/src/compiler/scala/reflect/std/Positions.scala
new file mode 100644
index 0000000000..a6ce52f7c6
--- /dev/null
+++ b/src/compiler/scala/reflect/std/Positions.scala
@@ -0,0 +1,13 @@
+package scala.reflect
+package std
+
+trait Positions {
+
+ class Position {
+ def focus: Position = this
+ def isRange: Boolean = false
+ def show: String = toString
+ }
+
+ val NoPosition: Position = new Position
+}
diff --git a/src/compiler/scala/reflect/std/ReflectSettings.scala b/src/compiler/scala/reflect/std/ReflectSettings.scala
new file mode 100644
index 0000000000..a520e1fb89
--- /dev/null
+++ b/src/compiler/scala/reflect/std/ReflectSettings.scala
@@ -0,0 +1,23 @@
+package scala.reflect
+package std
+
+class ReflectSettings extends common.settings.MutableSettings {
+
+ def newSetting[TT](init: TT) = new SettingValue {
+ type T = TT
+ def postSetHook() {}
+ var v = init
+ override def isDefault = v == init
+ }
+
+ val debug = newSetting(false)
+ val YdepMethTpes = newSetting(false)
+ val Ynotnull = newSetting(false)
+ val explaintypes = newSetting(false)
+ val verbose = newSetting(false)
+ val uniqid = newSetting(false)
+ val Xprintpos = newSetting(false)
+ val printtypes = newSetting(false)
+ val Yrecursion = newSetting(0)
+ val maxClassfileName = newSetting(255)
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/std/SymbolCompleters.scala b/src/compiler/scala/reflect/std/SymbolCompleters.scala
new file mode 100644
index 0000000000..678caf500a
--- /dev/null
+++ b/src/compiler/scala/reflect/std/SymbolCompleters.scala
@@ -0,0 +1,80 @@
+package scala.reflect
+package std
+
+import java.io.File
+import common._
+
+trait SymbolCompleters { self: Mirror =>
+
+ class PackageCompleter(owner: Symbol) extends LazyType {
+ override def isComplete = true
+ override def complete(sym: Symbol) {}
+
+ private val knownMembers = new Scope
+
+ override def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = {
+ if (name == nme.ANYNAME) abort("cannot enumerate members of a package")
+ else {
+ val sym = knownMembers.lookup(name)
+ if (sym != NoSymbol) sym
+ else {
+ def prepare(sym: Symbol, tpe: Type): Symbol = {
+ knownMembers.enter(sym)
+ sym.setInfo(tpe)
+ }
+ try {
+ val prefix = if (owner.isRoot) "" else owner.fullName + "."
+ val jclazz = java.lang.Class.forName(prefix + name)
+ val classRoot = owner.newClass(NoPosition, name.toTypeName)
+ val moduleRoot = owner.newModule(NoPosition, name.toTermName)
+ val loader = new ClassCompleter(classRoot, moduleRoot, jclazz)
+ prepare(classRoot, loader)
+ prepare(moduleRoot, loader)
+ if (name.isTypeName) classRoot else moduleRoot
+ } catch {
+ case ex: ClassNotFoundException =>
+ if (name.isTermName) {
+ // looking for module, construct package symbol instead
+ val pkg = owner.newPackage(NoPosition, name)
+ prepare(pkg, new PackageCompleter(pkg))
+ } else
+ NoSymbol
+ }
+ }
+ }
+ }
+ }
+
+ class ClassCompleter(classRoot: Symbol, moduleRoot: Symbol, jclazz: java.lang.Class[_]) extends LazyType {
+
+ import definitions._
+
+ def scalaSigAttr(jclazz: java.lang.Class[_]): Option[Array[Byte]] =
+ jclazz.getAnnotation(classOf[ScalaSignature]) match {
+ case sig: ScalaSignature => Some(sig.bytes.getBytes())
+ case _ => jclazz.getAnnotation(classOf[ScalaLongSignature]) match {
+ case sig: ScalaLongSignature => Some(sig.bytes flatMap (_.getBytes))
+ case _ => None
+ }
+ }
+
+ def readJava(classRoot: Symbol, moduleRoot: Symbol) {
+ }
+
+ var _isComplete = false
+ override def isComplete = _isComplete
+
+ override def complete(sym: Symbol) {
+ _isComplete = true
+ scalaSigAttr(jclazz) match {
+ case Some(bytes) =>
+ val filename = classRoot.fullName.replace('.', File.separatorChar)
+ unpickler.unpickle(bytes, 0, classRoot, moduleRoot, filename)
+ case None =>
+ readJava(classRoot, moduleRoot)
+ }
+ }
+ }
+
+ val rootLoader = new PackageCompleter(definitions.RootClass)
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/cmd/program/Tokens.scala b/src/compiler/scala/tools/cmd/program/Tokens.scala
index be5e9e411a..c62f17cc35 100644
--- a/src/compiler/scala/tools/cmd/program/Tokens.scala
+++ b/src/compiler/scala/tools/cmd/program/Tokens.scala
@@ -8,7 +8,7 @@ package cmd
package program
import nsc._
-import util.Chars.char2uescape
+import scala.reflect.Chars.char2uescape
import io._
import ast.parser.Tokens._
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index 3338d1433d..98ac0ebd68 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -13,7 +13,7 @@ trait CompilationUnits { self: Global =>
/** One unit of compilation that has been submitted to the compiler.
* It typically corresponds to a single file of source code. It includes
* error-reporting hooks. */
- class CompilationUnit(val source: SourceFile) extends CompilationUnitTrait {
+ class CompilationUnit(val source: SourceFile) {
/** the fresh name creator */
var fresh: FreshNameCreator = new FreshNameCreator.Default
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
index 866975b414..e72bc705c1 100644
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
@@ -145,7 +145,7 @@ class StandardCompileServer extends SocketServer {
else {
if (isCompilerReusable) {
info("[Reusing existing Global instance.]")
- compiler.settings = newSettings
+ compiler.currentSettings = newSettings
compiler.reporter = reporter
}
else {
diff --git a/src/compiler/scala/tools/nsc/FatalError.scala b/src/compiler/scala/tools/nsc/FatalError.scala
index a18c98f7d4..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/FatalError.scala
+++ b/src/compiler/scala/tools/nsc/FatalError.scala
@@ -1,19 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-
-import scala.util.control.ControlThrowable
-
-case class FatalError(msg: String) extends Throwable(msg)
-
-class MissingRequirementError(val req: String) extends FatalError(req + " not found.")
-
-object MissingRequirementError {
- def unapply(x: Throwable) = x match {
- case x: MissingRequirementError => Some(x.req)
- case _ => None
- }
-}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 6af7fe991f..98937b8d83 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -13,8 +13,8 @@ import scala.tools.util.Profiling
import scala.collection.{ mutable, immutable }
import io.{ SourceReader, AbstractFile, Path }
import reporters.{ Reporter, ConsoleReporter }
-import util.{ Exceptional, ClassPath, SourceFile, Statistics, BatchSourceFile, ScriptSourceFile, ShowPickled, returning }
-import reflect.generic.{ PickleBuffer, PickleFormat }
+import util.{ Exceptional, ClassPath, SourceFile, Statistics, StatisticsInfo, BatchSourceFile, ScriptSourceFile, ShowPickled, returning }
+import scala.reflect.common.pickling.{ PickleBuffer, PickleFormat }
import settings.{ AestheticSettings }
import symtab.{ Flags, SymbolTable, SymbolLoaders, SymbolTrackers }
@@ -32,11 +32,17 @@ import backend.jvm.GenJVM
import backend.opt.{ Inliners, ClosureElimination, DeadCodeElimination }
import backend.icode.analysis._
-class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
- with CompilationUnits
- with Plugins
- with PhaseAssembly
-{
+class Global(var currentSettings: Settings, var reporter: Reporter) extends SymbolTable
+ with CompilationUnits
+ with Plugins
+ with PhaseAssembly
+ with Trees
+ with TreePrinters
+ with DocComments
+ with symtab.Positions {
+
+ override def settings = currentSettings
+
// alternate constructors ------------------------------------------
def this(reporter: Reporter) =
@@ -45,6 +51,15 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
def this(settings: Settings) =
this(settings, new ConsoleReporter(settings))
+ // fulfilling requirements
+
+ type AbstractFile = scala.tools.nsc.io.AbstractFile
+ val AbstractFile = scala.tools.nsc.io.AbstractFile
+
+ def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = gen.mkAttributedQualifier(tpe, termSym)
+
+ def picklerPhase: Phase = currentRun.picklerPhase
+
// platform specific elements
type ThisPlatform = Platform[_] { val global: Global.this.type }
@@ -103,7 +118,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
/** Some statistics (normally disabled) set with -Ystatistics */
object statistics extends {
val global: Global.this.type = Global.this
- } with Statistics
+ } with StatisticsInfo
/** Print tree in detailed form */
object nodePrinters extends {
@@ -602,7 +617,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
/* The set of phase objects that is the basis for the compiler phase chain */
protected lazy val phasesSet = new mutable.HashSet[SubComponent]
protected lazy val phasesDescMap = new mutable.HashMap[SubComponent, String] withDefaultValue ""
- private lazy val phaseTimings = new Phase.TimingModel // tracking phase stats
+ private lazy val phaseTimings = new Phases.TimingModel // tracking phase stats
protected def addToPhasesSet(sub: SubComponent, descr: String) {
phasesSet += sub
phasesDescMap(sub) = descr
@@ -1221,7 +1236,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
// to false except in old code. The downside is that this leaves us calling a
// deprecated method: but I see no simple way out, so I leave it for now.
def forJVM = opt.jvm
- def forMSIL = opt.msil
+ override def forMSIL = opt.msil
def forInteractive = onlyPresentation
def forScaladoc = onlyPresentation
def createJavadoc = false
diff --git a/src/compiler/scala/tools/nsc/NoPhase.scala b/src/compiler/scala/tools/nsc/NoPhase.scala
index a74d14acf7..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/NoPhase.scala
+++ b/src/compiler/scala/tools/nsc/NoPhase.scala
@@ -1,11 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2007-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-
-object NoPhase extends Phase(null) {
- def name = "<no phase>"
- def run() { throw new Error("NoPhase.run") }
-}
diff --git a/src/compiler/scala/tools/nsc/Phase.scala b/src/compiler/scala/tools/nsc/Phase.scala
index f79b7c4367..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/Phase.scala
+++ b/src/compiler/scala/tools/nsc/Phase.scala
@@ -1,85 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-
-import symtab.Flags
-import util.TableDef
-
-abstract class Phase(val prev: Phase) {
-
- type Id = Int
-
- val id: Id = if (prev eq null) 0 else prev.id + 1
-
- /** New flags visible after this phase has completed */
- def nextFlags: Long = 0l
-
- /** New flags visible once this phase has started */
- def newFlags: Long = 0l
-
- private var fmask: Long =
- if (prev eq null) Flags.InitialFlags else prev.flagMask | prev.nextFlags | newFlags
- def flagMask: Long = fmask
-
- private var nx: Phase = this
- if ((prev ne null) && (prev ne NoPhase)) prev.nx = this
-
- def next: Phase = nx
-
- def name: String
- def description: String = name
- // Will running with -Ycheck:name work?
- def checkable: Boolean = true
- // def devirtualized: Boolean = false
- def specialized: Boolean = false
- def erasedTypes: Boolean = false
- def flatClasses: Boolean = false
- def refChecked: Boolean = false
- def keepsTypeParams = true
- def run(): Unit
-
- override def toString() = name
- override def hashCode = id.## + name.##
- override def equals(other: Any) = other match {
- case x: Phase => id == x.id && name == x.name
- case _ => false
- }
-}
-
-object Phase {
- val MaxPhases = 64
-
- /** A class for tracking something about each phase.
- */
- class Model[T: Manifest] {
- case class Cell(ph: Phase, value: T) {
- def name = ph.name
- def id = ph.id
- }
- val values = new Array[Cell](MaxPhases + 1)
- def results = values filterNot (_ == null)
- def apply(ph: Phase): T = values(ph.id).value
- def update(ph: Phase, value: T): Unit = values(ph.id) = Cell(ph, value)
- }
- /** A class for recording the elapsed time of each phase in the
- * interests of generating a classy and informative table.
- */
- class TimingModel extends Model[Long] {
- var total: Long = 0
- def table() = {
- total = results map (_.value) sum;
- new Format.Table(results sortBy (-_.value))
- }
- object Format extends TableDef[Cell] {
- >> ("phase" -> (_.name)) >+ " "
- << ("id" -> (_.id)) >+ " "
- >> ("ms" -> (_.value)) >+ " "
- << ("share" -> (_.value.toDouble * 100 / total formatted "%.2f"))
- }
- def formatted = "" + table()
- }
-}
-
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
index be729904db..91d8f9fb87 100755
--- a/src/compiler/scala/tools/nsc/ast/DocComments.scala
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
@@ -17,7 +17,7 @@ import scala.collection.mutable.{HashMap, ListBuffer, StringBuilder}
* @author Martin Odersky
* @version 1.0
*/
-trait DocComments { self: SymbolTable =>
+trait DocComments { self: Global =>
def reporter: Reporter
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index af2ebc4251..29dc2c62d5 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -13,199 +13,12 @@ import symtab.SymbolTable
/** XXX to resolve: TreeGen only assumes global is a SymbolTable, but
* TreeDSL at the moment expects a Global. Can we get by with SymbolTable?
*/
-abstract class TreeGen {
- val global: SymbolTable
+abstract class TreeGen extends reflect.common.TreeGen {
+ val global: Global
import global._
import definitions._
- def rootId(name: Name) = Select(Ident(nme.ROOTPKG), name)
- def rootScalaDot(name: Name) = Select(rootId(nme.scala_) setSymbol ScalaPackage, name)
- def scalaDot(name: Name) = Select(Ident(nme.scala_) setSymbol ScalaPackage, name)
- def scalaAnyRefConstr = scalaDot(tpnme.AnyRef)
- def scalaUnitConstr = scalaDot(tpnme.Unit)
- def scalaScalaObjectConstr = scalaDot(tpnme.ScalaObject)
- def productConstr = scalaDot(tpnme.Product)
- def serializableConstr = scalaDot(tpnme.Serializable)
-
- def scalaFunctionConstr(argtpes: List[Tree], restpe: Tree, abstractFun: Boolean = false): Tree = {
- val cls = if (abstractFun)
- mkAttributedRef(AbstractFunctionClass(argtpes.length))
- else
- mkAttributedRef(FunctionClass(argtpes.length))
- AppliedTypeTree(cls, argtpes :+ restpe)
- }
-
- /** Builds a reference to value whose type is given stable prefix.
- * The type must be suitable for this. For example, it
- * must not be a TypeRef pointing to an abstract type variable.
- */
- def mkAttributedQualifier(tpe: Type): Tree =
- mkAttributedQualifier(tpe, NoSymbol)
-
- /** Builds a reference to value whose type is given stable prefix.
- * If the type is unsuitable, e.g. it is a TypeRef for an
- * abstract type variable, then an Ident will be made using
- * termSym as the Ident's symbol. In that case, termSym must
- * not be NoSymbol.
- */
- def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = tpe match {
- case NoPrefix =>
- EmptyTree
- case ThisType(clazz) =>
- if (clazz.isEffectiveRoot) EmptyTree
- else mkAttributedThis(clazz)
- case SingleType(pre, sym) =>
- applyIfNoArgs(mkAttributedStableRef(pre, sym))
- case TypeRef(pre, sym, args) =>
- if (sym.isRoot) {
- mkAttributedThis(sym)
- } else if (sym.isModuleClass) {
- applyIfNoArgs(mkAttributedRef(pre, sym.sourceModule))
- } else if (sym.isModule || sym.isClass) {
- assert(phase.erasedTypes, tpe)
- mkAttributedThis(sym)
- } else if (sym.isType) {
- assert(termSym != NoSymbol, tpe)
- mkAttributedIdent(termSym) setType tpe
- } else {
- mkAttributedRef(pre, sym)
- }
-
- case ConstantType(value) =>
- Literal(value) setType tpe
-
- case AnnotatedType(_, atp, _) =>
- mkAttributedQualifier(atp)
-
- case RefinedType(parents, _) =>
- // I am unclear whether this is reachable, but
- // the following implementation looks logical -Lex
- val firstStable = parents.find(_.isStable)
- assert(!firstStable.isEmpty, tpe)
- mkAttributedQualifier(firstStable.get)
-
- case _ =>
- abort("bad qualifier: " + tpe)
- }
- /** If this is a reference to a method with an empty
- * parameter list, wrap it in an apply.
- */
- private def applyIfNoArgs(qual: Tree) = qual.tpe match {
- case MethodType(Nil, restpe) => Apply(qual, Nil) setType restpe
- case _ => qual
- }
-
- /** Builds a reference to given symbol with given stable prefix. */
- def mkAttributedRef(pre: Type, sym: Symbol): Tree = {
- val qual = mkAttributedQualifier(pre)
- qual match {
- case EmptyTree => mkAttributedIdent(sym)
- case This(clazz) if qual.symbol.isEffectiveRoot => mkAttributedIdent(sym)
- case _ => mkAttributedSelect(qual, sym)
- }
- }
-
- /** Builds a reference to given symbol. */
- def mkAttributedRef(sym: Symbol): Tree =
- if (sym.owner.isClass) mkAttributedRef(sym.owner.thisType, sym)
- else mkAttributedIdent(sym)
-
- /** Builds an untyped reference to given symbol. */
- def mkUnattributedRef(sym: Symbol): Tree =
- if (sym.owner.isClass) Select(This(sym.owner), sym)
- else Ident(sym)
-
- /** Replaces tree type with a stable type if possible */
- def stabilize(tree: Tree): Tree = {
- for(tp <- stableTypeFor(tree)) tree.tpe = tp
- tree
- }
-
- /** Computes stable type for a tree if possible */
- def stableTypeFor(tree: Tree): Option[Type] = tree match {
- case Ident(_) if tree.symbol.isStable =>
- Some(singleType(tree.symbol.owner.thisType, tree.symbol))
- case Select(qual, _) if ((tree.symbol ne null) && (qual.tpe ne null)) && // turned assert into guard for #4064
- tree.symbol.isStable && qual.tpe.isStable =>
- Some(singleType(qual.tpe, tree.symbol))
- case _ =>
- None
- }
-
- /** Cast `tree' to type `pt' */
- def mkCast(tree: Tree, pt: Type): Tree = {
- if (settings.debug.value) log("casting " + tree + ":" + tree.tpe + " to " + pt)
- assert(!tree.tpe.isInstanceOf[MethodType], tree)
- assert(!pt.typeSymbol.isPackageClass)
- assert(!pt.typeSymbol.isPackageObjectClass)
- assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize)) //@MAT only called during erasure, which already takes care of that
- atPos(tree.pos)(mkAsInstanceOf(tree, pt, false))
- }
-
- /** Builds a reference with stable type to given symbol */
- def mkAttributedStableRef(pre: Type, sym: Symbol): Tree =
- stabilize(mkAttributedRef(pre, sym))
-
- def mkAttributedStableRef(sym: Symbol): Tree =
- stabilize(mkAttributedRef(sym))
-
- def mkAttributedThis(sym: Symbol): Tree =
- This(sym.name.toTypeName) setSymbol sym setType sym.thisType
-
- def mkAttributedIdent(sym: Symbol): Tree =
- Ident(sym.name) setSymbol sym setType sym.tpe
-
- def mkAttributedSelect(qual: Tree, sym: Symbol): Tree = {
- // Tests involving the repl fail without the .isEmptyPackage condition.
- if (qual.symbol != null && (qual.symbol.isEffectiveRoot || qual.symbol.isEmptyPackage))
- mkAttributedIdent(sym)
- else {
- val pkgQualifier =
- if (sym != null && sym.owner.isPackageObjectClass && sym.owner.owner == qual.tpe.typeSymbol) {
- val obj = sym.owner.sourceModule
- Select(qual, nme.PACKAGEkw) setSymbol obj setType singleType(qual.tpe, obj)
- }
- else qual
-
- val tree = Select(pkgQualifier, sym)
- if (pkgQualifier.tpe == null) tree
- else tree setType (qual.tpe memberType sym)
- }
- }
-
- private def mkTypeApply(value: Tree, tpe: Type, what: Symbol) =
- Apply(
- TypeApply(
- mkAttributedSelect(value, what),
- List(TypeTree(tpe.normalize))
- ),
- Nil
- )
- /** Builds an instance test with given value and type. */
- def mkIsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree =
- mkTypeApply(value, tpe, (if (any) Any_isInstanceOf else Object_isInstanceOf))
-
- /** Builds a cast with given value and type. */
- def mkAsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree =
- mkTypeApply(value, tpe, (if (any) Any_asInstanceOf else Object_asInstanceOf))
-
- /** Cast `tree' to 'pt', unless tpe is a subtype of pt, or pt is Unit. */
- def maybeMkAsInstanceOf(tree: Tree, pt: Type, tpe: Type, beforeRefChecks: Boolean = false): Tree =
- if ((pt == UnitClass.tpe) || (tpe <:< pt)) {
- log("no need to cast from " + tpe + " to " + pt)
- tree
- } else
- atPos(tree.pos) {
- if (beforeRefChecks)
- TypeApply(mkAttributedSelect(tree, Any_asInstanceOf), List(TypeTree(pt)))
- else
- mkAsInstanceOf(tree, pt)
- }
-
- def mkClassOf(tp: Type): Tree =
- Literal(Constant(tp)) setType ConstantType(Constant(tp))// ClassType(tp)
-
def mkCheckInit(tree: Tree): Tree = {
val tpe =
if (tree.tpe != null || !tree.hasSymbol) tree.tpe
@@ -218,44 +31,6 @@ abstract class TreeGen {
tree
}
- /** Builds a list with given head and tail. */
- def mkNewCons(head: Tree, tail: Tree): Tree =
- New(Apply(mkAttributedRef(ConsClass), List(head, tail)))
-
- /** Builds a list with given head and tail. */
- def mkNil: Tree = mkAttributedRef(NilModule)
-
- /** Builds a tree representing an undefined local, as in
- * var x: T = _
- * which is appropriate to the given Type.
- */
- def mkZero(tp: Type): Tree = {
- val sym = tp.typeSymbol
- val tree =
- if (sym == UnitClass) Literal(())
- else if (sym == BooleanClass) Literal(false)
- else if (isValueClass(sym)) Literal(0)
- else if (NullClass.tpe <:< tp) Literal(null: Any)
- else abort("Cannot determine zero for " + tp)
-
- tree setType tp
- }
-
- /** Builds a tuple */
- def mkTuple(elems: List[Tree]): Tree =
- if (elems.isEmpty) Literal(())
- else Apply(
- Select(mkAttributedRef(TupleClass(elems.length).caseModule), nme.apply),
- elems)
-
- // tree1 AND tree2
- def mkAnd(tree1: Tree, tree2: Tree): Tree =
- Apply(Select(tree1, Boolean_and), List(tree2))
-
- // tree1 OR tree2
- def mkOr(tree1: Tree, tree2: Tree): Tree =
- Apply(Select(tree1, Boolean_or), List(tree2))
-
// wrap the given expression in a SoftReference so it can be gc-ed
def mkSoftRef(expr: Tree): Tree = New(TypeTree(SoftReferenceClass.tpe), List(List(expr)))
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 96f4355590..8c22f750b6 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -10,418 +10,13 @@ import java.io.{ OutputStream, PrintWriter, StringWriter, Writer }
import symtab.Flags._
import symtab.SymbolTable
-trait TreePrinters { trees: SymbolTable =>
+trait TreePrinters extends reflect.common.TreePrinters { this: Global =>
import treeInfo.{ IsTrue, IsFalse }
- final val showOuterTests = false
+ class TreePrinter(out: PrintWriter) extends super.TreePrinter(out) {
- /** Adds backticks if the name is a scala keyword. */
- def quotedName(name: Name, decode: Boolean): String = {
- val s = if (decode) name.decode else name.toString
- val term = name.toTermName
- if (nme.keywords(term) && term != nme.USCOREkw) "`%s`" format s
- else s
- }
- def quotedName(name: Name): String = quotedName(name, false)
-
- /** Turns a path into a String, introducing backquotes
- * as necessary.
- */
- def backquotedPath(t: Tree): String = t match {
- case Select(qual, name) => "%s.%s".format(backquotedPath(qual), quotedName(name))
- case Ident(name) => quotedName(name)
- case _ => t.toString
- }
-
- class TreePrinter(out: PrintWriter) extends trees.AbsTreePrinter(out) {
- protected var indentMargin = 0
- protected val indentStep = 2
- protected var indentString = " " // 40
-
- def flush() = out.flush()
-
- def indent() = indentMargin += indentStep
- def undent() = indentMargin -= indentStep
-
- protected def doPrintPositions = settings.Xprintpos.value
- def printPosition(tree: Tree) = if (doPrintPositions) print(tree.pos.show)
-
- def println() {
- out.println()
- while (indentMargin > indentString.length())
- indentString += indentString
- if (indentMargin > 0)
- out.write(indentString, 0, indentMargin)
- }
-
- def printSeq[a](ls: List[a])(printelem: a => Unit)(printsep: => Unit) {
- ls match {
- case List() =>
- case List(x) => printelem(x)
- case x :: rest => printelem(x); printsep; printSeq(rest)(printelem)(printsep)
- }
- }
-
- def printColumn(ts: List[Tree], start: String, sep: String, end: String) {
- print(start); indent; println()
- printSeq(ts){print}{print(sep); println()}; undent; println(); print(end)
- }
-
- def printRow(ts: List[Tree], start: String, sep: String, end: String) {
- print(start); printSeq(ts){print}{print(sep)}; print(end)
- }
-
- def printRow(ts: List[Tree], sep: String) { printRow(ts, "", sep, "") }
-
- def printTypeParams(ts: List[TypeDef]) {
- if (!ts.isEmpty) {
- print("["); printSeq(ts){ t =>
- printAnnotations(t)
- printParam(t)
- }{print(", ")}; print("]")
- }
- }
-
- def printValueParams(ts: List[ValDef]) {
- print("(")
- if (!ts.isEmpty) printFlags(ts.head.mods.flags & IMPLICIT, "")
- printSeq(ts){printParam}{print(", ")}
- print(")")
- }
-
- def printParam(tree: Tree) {
- tree match {
- case ValDef(mods, name, tp, rhs) =>
- printPosition(tree)
- printAnnotations(tree)
- print(symName(tree, name)); printOpt(": ", tp); printOpt(" = ", rhs)
- case TypeDef(mods, name, tparams, rhs) =>
- printPosition(tree)
- print(symName(tree, name))
- printTypeParams(tparams); print(rhs)
- }
- }
-
- def printBlock(tree: Tree) {
- tree match {
- case Block(_, _) =>
- print(tree)
- case _ =>
- printColumn(List(tree), "{", ";", "}")
- }
- }
-
- private def symFn[T](tree: Tree, f: Symbol => T, orElse: => T): T = tree.symbol match {
- case null | NoSymbol => orElse
- case sym => f(sym)
- }
- private def ifSym(tree: Tree, p: Symbol => Boolean) = symFn(tree, p, false)
-
- private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = {
- def nameFn(sym: Symbol) = {
- val prefix = if (sym.isMixinConstructor) "/*%s*/".format(quotedName(sym.owner.name, decoded)) else ""
- prefix + tree.symbol.nameString
- }
- symFn(tree, nameFn, quotedName(name, decoded))
- }
-
- def decodedSymName(tree: Tree, name: Name) = symNameInternal(tree, name, true)
- def symName(tree: Tree, name: Name) = symNameInternal(tree, name, false)
-
- def printOpt(prefix: String, tree: Tree) {
- if (!tree.isEmpty) { print(prefix); print(tree) }
- }
-
- def printModifiers(tree: Tree, mods: Modifiers): Unit = printFlags(
- if (tree.symbol == NoSymbol) mods.flags else tree.symbol.flags, "" + (
- if (tree.symbol == NoSymbol) mods.privateWithin
- else if (tree.symbol.hasAccessBoundary) tree.symbol.privateWithin.name
- else ""
- )
- )
-
- def printFlags(flags: Long, privateWithin: String) {
- var mask: Long = if (settings.debug.value) -1L else PrintableFlags
- val s = flagsToString(flags & mask, privateWithin)
- if (s != "") print(s + " ")
- }
-
- def printAnnotations(tree: Tree) {
- val annots =
- if (tree.symbol.hasAssignedAnnotations) tree.symbol.annotations
- else tree.asInstanceOf[MemberDef].mods.annotations
-
- annots foreach (annot => print("@"+annot+" "))
- }
-
- def print(str: String) { out.print(str) }
- def print(name: Name) { print(quotedName(name)) }
-
- private var currentOwner: Symbol = NoSymbol
- private var selectorType: Type = NoType
-
- def printRaw(tree: Tree) {
- tree match {
- case EmptyTree =>
- print("<empty>")
-
- case ClassDef(mods, name, tparams, impl) =>
- printAnnotations(tree)
- printModifiers(tree, mods)
- val word =
- if (mods.hasTraitFlag) "trait"
- else if (ifSym(tree, _.isModuleClass)) "object"
- else "class"
-
- print(word + " " + symName(tree, name))
- printTypeParams(tparams)
- print(if (mods.isDeferred) " <: " else " extends "); print(impl)
-
- case PackageDef(packaged, stats) =>
- printAnnotations(tree)
- print("package "); print(packaged); printColumn(stats, " {", ";", "}")
-
- case ModuleDef(mods, name, impl) =>
- printAnnotations(tree)
- printModifiers(tree, mods); print("object " + symName(tree, name))
- print(" extends "); print(impl)
-
- case ValDef(mods, name, tp, rhs) =>
- printAnnotations(tree)
- printModifiers(tree, mods)
- print(if (mods.isMutable) "var " else "val ")
- print(symName(tree, name))
- printOpt(": ", tp)
- if (!mods.isDeferred) {
- print(" = ")
- if (rhs.isEmpty) print("_") else print(rhs)
- }
-
- case DefDef(mods, name, tparams, vparamss, tp, rhs) =>
- printAnnotations(tree)
- printModifiers(tree, mods)
- print("def " + symName(tree, name))
- printTypeParams(tparams); vparamss foreach printValueParams
- printOpt(": ", tp); printOpt(" = ", rhs)
-
- case TypeDef(mods, name, tparams, rhs) =>
- if (mods hasFlag (PARAM | DEFERRED)) {
- printAnnotations(tree)
- printModifiers(tree, mods); print("type "); printParam(tree)
- } else {
- printAnnotations(tree)
- printModifiers(tree, mods); print("type " + symName(tree, name))
- printTypeParams(tparams); printOpt(" = ", rhs)
- }
-
- case LabelDef(name, params, rhs) =>
- print(symName(tree, name)); printRow(params, "(", ",", ")"); printBlock(rhs)
-
- case Import(expr, selectors) =>
- // Is this selector remapping a name (i.e, {name1 => name2})
- def isNotRemap(s: ImportSelector) : Boolean = (s.name == nme.WILDCARD || s.name == s.rename)
- def selectorToString(s: ImportSelector): String = {
- val from = quotedName(s.name)
- if (isNotRemap(s)) from
- else from + "=>" + quotedName(s.rename)
- }
- print("import "); print(backquotedPath(expr))
- print(".")
- selectors match {
- case List(s) =>
- // If there is just one selector and it is not remapping a name, no braces are needed
- if (isNotRemap(s)) {
- print(selectorToString(s))
- } else {
- print("{"); print(selectorToString(s)); print("}")
- }
- // If there is more than one selector braces are always needed
- case many =>
- print(many.map(selectorToString).mkString("{", ", ", "}"))
- }
-
- case DocDef(comment, definition) =>
- print(comment.raw); println(); print(definition)
-
- case Template(parents, self, body) =>
- val currentOwner1 = currentOwner
- if (tree.symbol != NoSymbol) currentOwner = tree.symbol.owner
- printRow(parents, " with ")
- if (!body.isEmpty) {
- if (self.name != nme.WILDCARD) {
- print(" { "); print(self.name); printOpt(": ", self.tpt); print(" => ")
- } else if (!self.tpt.isEmpty) {
- print(" { _ : "); print(self.tpt); print(" => ")
- } else {
- print(" {")
- }
- printColumn(body, "", ";", "}")
- }
- currentOwner = currentOwner1
-
- case Block(stats, expr) =>
- printColumn(stats ::: List(expr), "{", ";", "}")
-
- case Match(selector, cases) =>
- val selectorType1 = selectorType
- selectorType = selector.tpe
- print(selector); printColumn(cases, " match {", "", "}")
- selectorType = selectorType1
-
- case CaseDef(pat, guard, body) =>
- print("case ")
- def patConstr(pat: Tree): Tree = pat match {
- case Apply(fn, args) => patConstr(fn)
- case _ => pat
- }
- if (showOuterTests &&
- needsOuterTest(
- patConstr(pat).tpe.finalResultType, selectorType, currentOwner))
- print("???")
- print(pat); printOpt(" if ", guard)
- print(" => "); print(body)
-
- case Alternative(trees) =>
- printRow(trees, "(", "| ", ")")
-
- case Star(elem) =>
- print("("); print(elem); print(")*")
-
- case Bind(name, t) =>
- print("("); print(symName(tree, name)); print(" @ "); print(t); print(")")
-
- case UnApply(fun, args) =>
- print(fun); print(" <unapply> "); printRow(args, "(", ", ", ")")
-
- case ArrayValue(elemtpt, trees) =>
- print("Array["); print(elemtpt); printRow(trees, "]{", ", ", "}")
-
- case Function(vparams, body) =>
- print("("); printValueParams(vparams); print(" => "); print(body); print(")")
- if (settings.uniqid.value && tree.symbol != null) print("#"+tree.symbol.id)
-
- case Assign(lhs, rhs) =>
- print(lhs); print(" = "); print(rhs)
-
- case AssignOrNamedArg(lhs, rhs) =>
- print(lhs); print(" = "); print(rhs)
-
- case If(cond, thenp, elsep) =>
- print("if ("); print(cond); print(")"); indent; println()
- print(thenp); undent
- if (!elsep.isEmpty) {
- println(); print("else"); indent; println(); print(elsep); undent
- }
-
- case Return(expr) =>
- print("return "); print(expr)
-
- case Try(block, catches, finalizer) =>
- print("try "); printBlock(block)
- if (!catches.isEmpty) printColumn(catches, " catch {", "", "}")
- printOpt(" finally ", finalizer)
-
- case Throw(expr) =>
- print("throw "); print(expr)
-
- case New(tpe) =>
- print("new "); print(tpe)
-
- case Typed(expr, tp) =>
- print("("); print(expr); print(": "); print(tp); print(")")
-
- case TypeApply(fun, targs) =>
- print(fun); printRow(targs, "[", ", ", "]")
-
- case Apply(fun, vargs) =>
- print(fun); printRow(vargs, "(", ", ", ")")
-
- case ApplyDynamic(qual, vargs) =>
- print("<apply-dynamic>("); print(qual); print("#"); print(tree.symbol.nameString)
- printRow(vargs, ", (", ", ", "))")
-
- case Super(This(qual), mix) =>
- if (!qual.isEmpty || tree.symbol != NoSymbol) print(symName(tree, qual) + ".")
- print("super")
- if (!mix.isEmpty)
- print("[" + mix + "]")
-
- case Super(qual, mix) =>
- print(qual)
- print(".super")
- if (!mix.isEmpty)
- print("[" + mix + "]")
-
- case This(qual) =>
- if (!qual.isEmpty) print(symName(tree, qual) + ".")
- print("this")
-
- case Select(qual @ New(tpe), name) if (!settings.debug.value) =>
- print(qual)
-
- case Select(qualifier, name) =>
- print(backquotedPath(qualifier)); print("."); print(symName(tree, name))
-
- case Ident(name) =>
- print(symName(tree, name))
-
- case Literal(x) =>
- print(x.escapedStringValue)
-
- case tt: TypeTree =>
- if ((tree.tpe eq null) || (settings.Xprintpos.value && tt.original != null)) {
- if (tt.original != null) { print("<type: "); print(tt.original); print(">") }
- else print("<type ?>")
- } else if ((tree.tpe.typeSymbol ne null) && tree.tpe.typeSymbol.isAnonymousClass) {
- print(tree.tpe.typeSymbol.toString())
- } else {
- print(tree.tpe.toString())
- }
-
- case Annotated(Apply(Select(New(tpt), nme.CONSTRUCTOR), args), tree) =>
- def printAnnot() {
- print("@"); print(tpt)
- if (!args.isEmpty)
- printRow(args, "(", ",", ")")
- }
- if (tree.isType) { print(tree); print(" "); printAnnot() }
- else { print(tree); print(": "); printAnnot() }
-
- case SingletonTypeTree(ref) =>
- print(ref); print(".type")
-
- case SelectFromTypeTree(qualifier, selector) =>
- print(qualifier); print("#"); print(symName(tree, selector))
-
- case CompoundTypeTree(templ) =>
- print(templ)
-
- case AppliedTypeTree(tp, args) =>
- print(tp); printRow(args, "[", ", ", "]")
-
- case TypeBoundsTree(lo, hi) =>
- printOpt(" >: ", lo); printOpt(" <: ", hi)
-
- case ExistentialTypeTree(tpt, whereClauses) =>
- print(tpt);
- printColumn(whereClauses, " forSome { ", ";", "}")
-
- case SelectFromArray(qualifier, name, _) =>
- print(qualifier); print(".<arr>"); print(symName(tree, name))
-
- case TypeTreeWithDeferredRefCheck() =>
- print("<tree with deferred refcheck>")
-
- case tree =>
- print("<unknown tree of class "+tree.getClass+">")
- }
- if (settings.printtypes.value && tree.isTerm && !tree.isEmpty) {
- print("{"); print(if (tree.tpe eq null) "<null>" else tree.tpe.toString()); print("}")
- }
- }
-
- def print(tree: Tree) {
+ override def print(tree: Tree) {
printPosition(tree)
printRaw(
if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.isInitialized) {
@@ -685,24 +280,9 @@ trait TreePrinters { trees: SymbolTable =>
def newCompactTreePrinter(stream: OutputStream): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(stream))
def newCompactTreePrinter(): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(ConsoleWriter))
- def newTreePrinter(writer: PrintWriter): TreePrinter =
+ override def newTreePrinter(writer: PrintWriter): TreePrinter =
if (settings.Ycompacttrees.value) newCompactTreePrinter(writer)
else newStandardTreePrinter(writer)
- def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream))
- def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter))
-
- /** A writer that writes to the current Console and
- * is sensitive to replacement of the Console's
- * output stream.
- */
- object ConsoleWriter extends Writer {
- override def write(str: String) { Console.print(str) }
-
- def write(cbuf: Array[Char], off: Int, len: Int) {
- write(new String(cbuf, off, len))
- }
-
- def close = { /* do nothing */ }
- def flush = { /* do nothing */ }
- }
+ override def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream))
+ override def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter))
}
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 0e15979460..bb61534f16 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -6,1155 +6,11 @@
package scala.tools.nsc
package ast
-import scala.collection.mutable.ListBuffer
-import scala.tools.nsc.symtab.SymbolTable
-import scala.tools.nsc.symtab.Flags._
-import scala.tools.nsc.util.{ FreshNameCreator, HashSet, SourceFile }
-
-trait Trees extends reflect.generic.Trees { self: SymbolTable =>
-
- trait CompilationUnitTrait {
- var body: Tree
- val source: SourceFile
- def fresh : FreshNameCreator
- def freshTermName(prefix: String): TermName
- def freshTypeName(prefix: String): TypeName
- }
-
- type CompilationUnit <: CompilationUnitTrait
-
- protected def flagsIntoString(flags: Long, privateWithin: String): String = flagsToString(flags, privateWithin)
-
- // sub-components --------------------------------------------------
+trait Trees extends reflect.common.Trees { self: Global =>
lazy val treePrinter = newTreePrinter()
- object treeInfo extends {
- val trees: Trees.this.type = Trees.this
- } with TreeInfo
-
- val treeCopy = new LazyTreeCopier()
-
- implicit def treeWrapper(tree: Tree): TreeOps = new TreeOps(tree)
-
- class TreeOps(tree: Tree) {
- def isTerm: Boolean = tree 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 DocDef(_, defn) => defn.isTerm
- case _ => false
- }
-
- def isType: Boolean = tree 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 DocDef(_, defn) => defn.isType
- case _ => false
- }
-
- def isErroneous = (tree.tpe ne null) && tree.tpe.isErroneous
- def isTyped = (tree.tpe ne null) && !tree.tpe.isErroneous
-
- /** Apply `f' to each subtree */
- def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(tree) }
-
- /** If 'pf' is defined for a given subtree, call super.traverse(pf(tree)),
- * otherwise super.traverse(tree).
- */
- def foreachPartial(pf: PartialFunction[Tree, Tree]) { new ForeachPartialTreeTraverser(pf).traverse(tree) }
-
- /** Find all subtrees matching predicate `p' */
- def filter(f: Tree => Boolean): List[Tree] = {
- val ft = new FilterTreeTraverser(f)
- ft.traverse(tree)
- ft.hits.toList
- }
-
- /** Returns optionally first tree (in a preorder traversal) which satisfies predicate `p',
- * or None if none exists.
- */
- def find(p: Tree => Boolean): Option[Tree] = {
- val ft = new FindTreeTraverser(p)
- ft.traverse(tree)
- ft.result
- }
-
- def changeOwner(pairs: (Symbol, Symbol)*): Tree = {
- pairs.foldLeft(tree) { case (t, (oldOwner, newOwner)) =>
- new ChangeOwnerTraverser(oldOwner, newOwner) apply t
- }
- }
-
- /** Is there part of this tree which satisfies predicate `p'? */
- def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty
-
- def equalsStructure(that : Tree) = equalsStructure0(that)(_ eq _)
- def equalsStructure0(that: Tree)(f: (Tree,Tree) => Boolean): Boolean =
- f(tree, that) || ((tree.productArity == that.productArity) && {
- def equals0(this0: Any, that0: Any): Boolean = (this0, that0) match {
- case (x: Tree, y: Tree) => f(x, y) || (x equalsStructure0 y)(f)
- case (xs: List[_], ys: List[_]) => (xs corresponds ys)(equals0)
- case _ => this0 == that0
- }
- def compareOriginals() = (tree, that) match {
- case (x: TypeTree, y: TypeTree) if x.original != null && y.original != null =>
- (x.original equalsStructure0 y.original)(f)
- case _ =>
- true
- }
-
- (tree.productIterator zip that.productIterator forall { case (x, y) => equals0(x, y) }) && compareOriginals()
- })
-
- def shallowDuplicate: Tree = new ShallowDuplicator(tree) transform tree
- def shortClass: String = tree.getClass.getName split "[.$]" last
- }
-
- private[scala] override def duplicateTree(tree: Tree): Tree = duplicator transform tree
-
-// ---- values and creators ---------------------------------------
-
- /** @param sym the class symbol
- * @return the implementation template
- */
- def ClassDef(sym: Symbol, impl: Template): ClassDef =
- atPos(sym.pos) {
- ClassDef(Modifiers(sym.flags),
- sym.name.toTypeName,
- sym.typeParams map TypeDef,
- impl) setSymbol sym
- }
-
- /** Construct class definition with given class symbol, value parameters,
- * supercall arguments and template body.
- *
- * @param sym the class symbol
- * @param constrMods the modifiers for the class constructor, i.e. as in `class C private (...)'
- * @param vparamss the value parameters -- if they have symbols they
- * should be owned by `sym'
- * @param argss the supercall arguments
- * @param body the template statements without primary constructor
- * and value parameter fields.
- */
- def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): ClassDef =
- ClassDef(sym,
- Template(sym.info.parents map TypeTree,
- if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym),
- constrMods, vparamss, argss, body, superPos))
-
- /**
- * @param sym the class symbol
- * @param impl the implementation template
- */
- def ModuleDef(sym: Symbol, impl: Template): ModuleDef =
- atPos(sym.pos) {
- ModuleDef(Modifiers(sym.flags), sym.name, impl) setSymbol sym
- }
-
- def ValDef(sym: Symbol, rhs: Tree): ValDef =
- atPos(sym.pos) {
- ValDef(Modifiers(sym.flags), sym.name,
- TypeTree(sym.tpe) setPos sym.pos.focus,
- rhs) setSymbol sym
- }
-
- def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree)
-
- object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) {
- override def isEmpty = true
- super.setPos(NoPosition)
- override def setPos(pos: Position) = { assert(false); this }
- }
-
- def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef =
- atPos(sym.pos) {
- assert(sym != NoSymbol)
- DefDef(Modifiers(sym.flags),
- sym.name,
- sym.typeParams map TypeDef,
- vparamss,
- TypeTree(sym.tpe.finalResultType) setPos sym.pos.focus,
- rhs) setSymbol sym
- }
-
- def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef =
- DefDef(sym, Modifiers(sym.flags), vparamss, rhs)
-
- def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef =
- DefDef(sym, mods, sym.paramss map (_.map(ValDef)), rhs)
-
- def DefDef(sym: Symbol, rhs: Tree): DefDef =
- DefDef(sym, Modifiers(sym.flags), rhs)
-
- def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef = {
- DefDef(sym, rhs(sym.info.paramss))
- }
-
- /** A TypeDef node which defines given `sym' with given tight hand side `rhs'. */
- def TypeDef(sym: Symbol, rhs: Tree): TypeDef =
- atPos(sym.pos) {
- TypeDef(Modifiers(sym.flags), sym.name.toTypeName, sym.typeParams map TypeDef, rhs) setSymbol sym
- }
-
- /** A TypeDef node which defines abstract type or type parameter for given `sym' */
- def TypeDef(sym: Symbol): TypeDef =
- TypeDef(sym, TypeBoundsTree(TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi)))
-
- def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef =
- atPos(sym.pos) {
- LabelDef(sym.name, params map Ident, rhs) setSymbol sym
- }
-
- /** Generates a template with constructor corresponding to
- *
- * constrmods (vparams1_) ... (vparams_n) preSuper { presupers }
- * extends superclass(args_1) ... (args_n) with mixins { self => body }
- *
- * This gets translated to
- *
- * extends superclass with mixins { self =>
- * presupers' // presupers without rhs
- * vparamss // abstract fields corresponding to value parameters
- * def <init>(vparamss) {
- * presupers
- * super.<init>(args)
- * }
- * body
- * }
- */
- def Template(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): Template = {
- /* Add constructor to template */
-
- // create parameters for <init> as synthetic trees.
- var vparamss1 =
- vparamss map (vps => vps.map { vd =>
- atPos(vd.pos.focus) {
- ValDef(
- Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM | BYNAMEPARAM) | PARAM | PARAMACCESSOR) withAnnotations vd.mods.annotations,
- vd.name, vd.tpt.duplicate, vd.rhs.duplicate)
- }})
- val (edefs, rest) = body span treeInfo.isEarlyDef
- val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef
- val (lvdefs, gvdefs) = evdefs map {
- case vdef @ ValDef(mods, name, tpt, rhs) =>
- val fld = treeCopy.ValDef(
- vdef.duplicate, mods, name,
- atPos(vdef.pos.focus) { TypeTree() setOriginal tpt setPos tpt.pos.focus }, // atPos in case
- EmptyTree)
- val local = treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs)
- (local, fld)
- } unzip
-
- val constrs = {
- if (constrMods hasFlag TRAIT) {
- if (body forall treeInfo.isInterfaceMember) List()
- else List(
- atPos(wrappingPos(superPos, lvdefs)) (
- DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(lvdefs, Literal(())))))
- } else {
- // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section
- if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit)
- vparamss1 = List() :: vparamss1;
- val superRef: Tree = atPos(superPos) {
- Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR)
- }
- val superCall = (superRef /: argss) (Apply)
- List(
- atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) (
- DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(())))))
- }
- }
- // println("typed template, gvdefs = "+gvdefs+", parents = "+parents+", constrs = "+constrs)
- constrs foreach (ensureNonOverlapping(_, parents ::: gvdefs))
- // vparamss2 are used as field definitions for the class. remove defaults
- val vparamss2 = vparamss map (vps => vps map { vd =>
- treeCopy.ValDef(vd, vd.mods &~ DEFAULTPARAM, vd.name, vd.tpt, EmptyTree)
- })
- Template(parents, self, gvdefs ::: vparamss2.flatten ::: constrs ::: etdefs ::: rest)
- }
-
- /** casedef shorthand */
- def CaseDef(pat: Tree, body: Tree): CaseDef = CaseDef(pat, EmptyTree, body)
-
- def Bind(sym: Symbol, body: Tree): Bind =
- Bind(sym.name, body) setSymbol sym
-
-
- /** 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 = {
- assert(!argss.isEmpty)
- val superRef: Tree = Select(New(tpt), nme.CONSTRUCTOR)
- (superRef /: argss) (Apply)
- }
-
- def Apply(sym: Symbol, args: Tree*): Tree =
- Apply(Ident(sym), args.toList)
-
- def Super(sym: Symbol, mix: TypeName): Tree = Super(This(sym), mix)
-
- def This(sym: Symbol): Tree = This(sym.name.toTypeName) setSymbol sym
-
- def Select(qualifier: Tree, sym: Symbol): Select =
- Select(qualifier, sym.name) setSymbol sym
-
- def Ident(sym: Symbol): Ident =
- Ident(sym.name) setSymbol sym
-
- /** Block factory that flattens directly nested blocks.
- */
- def Block(stats: Tree*): Block = stats match {
- case Seq(b @ Block(_, _)) => b
- case Seq(stat) => Block(stats.toList, Literal(Constant(())))
- case Seq(_, rest @ _*) => Block(stats.init.toList, stats.last)
- }
-
- /** A synthetic term 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
- * <code>RefCheck</code>, where the arbitrary type trees are all replaced by
- * TypeTree's. */
- case class TypeTree() extends AbsTypeTree {
- private var orig: Tree = null
- private[Trees] var wasEmpty: Boolean = false
-
- def original: Tree = orig
- def setOriginal(tree: Tree): this.type = {
- def followOriginal(t: Tree): Tree = t match {
- case tt: TypeTree => followOriginal(tt.original)
- case t => t
- }
-
- orig = followOriginal(tree); setPos(tree.pos);
- this
- }
-
- override def defineType(tp: Type): this.type = {
- wasEmpty = isEmpty
- setType(tp)
- }
- }
-
- object TypeTree extends TypeTreeExtractor
-
- def TypeTree(tp: Type): TypeTree = TypeTree() setType tp
-
- /** Documented definition, eliminated by analyzer */
- case class DocDef(comment: DocComment, definition: Tree)
- extends Tree {
- override def symbol: Symbol = definition.symbol
- override def symbol_=(sym: Symbol) { definition.symbol = sym }
- // sean: seems to be important to the IDE
- override def isDef = definition.isDef
- }
-
- /** Either an assignment or a named argument. Only appears in argument lists,
- * eliminated by typecheck (doTypedApply)
- */
- case class AssignOrNamedArg(lhs: Tree, rhs: Tree)
- extends TermTree
-
- case class Parens(args: List[Tree]) extends Tree // only used during parsing
-
- /** emitted by typer, eliminated by refchecks */
- case class TypeTreeWithDeferredRefCheck()(val check: () => TypeTree) extends AbsTypeTree
-
-// ----- subconstructors --------------------------------------------
-
- class ApplyToImplicitArgs(fun: Tree, args: List[Tree]) extends Apply(fun, args)
-
- class ApplyImplicitView(fun: Tree, args: List[Tree]) extends Apply(fun, args)
-
-// ----- auxiliary objects and methods ------------------------------
-
- abstract class TreeCopier {
- def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef
- def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]): PackageDef
- def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef
- def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef
- def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef
- def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef
- def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef
- def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import
- def DocDef(tree: Tree, comment: DocComment, definition: Tree): DocDef
- def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template
- def Block(tree: Tree, stats: List[Tree], expr: Tree): Block
- def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef
- def Alternative(tree: Tree, trees: List[Tree]): Alternative
- 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
- def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If
- def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match
- def Return(tree: Tree, expr: Tree): Return
- def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try
- def Throw(tree: Tree, expr: Tree): Throw
- def New(tree: Tree, tpt: Tree): New
- def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed
- def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply
- def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply
- def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]): ApplyDynamic
- def Super(tree: Tree, qual: Tree, mix: TypeName): Super
- def This(tree: Tree, qual: Name): This
- def Select(tree: Tree, qualifier: Tree, selector: Name): Select
- def Ident(tree: Tree, name: Name): Ident
- def Literal(tree: Tree, value: Constant): Literal
- def TypeTree(tree: Tree): TypeTree
- def TypeTreeWithDeferredRefCheck(tree: Tree): TypeTreeWithDeferredRefCheck
- def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated
- def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree
- def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree
- def CompoundTypeTree(tree: Tree, templ: Template): CompoundTypeTree
- def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree
- def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree
- def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree
- def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type): SelectFromArray
- }
-
- class StrictTreeCopier extends TreeCopier {
- def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) =
- new ClassDef(mods, name.toTypeName, tparams, impl).copyAttrs(tree)
- def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) =
- new PackageDef(pid, stats).copyAttrs(tree)
- def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) =
- new ModuleDef(mods, name, impl).copyAttrs(tree)
- def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) =
- new ValDef(mods, name, tpt, rhs).copyAttrs(tree)
- def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) =
- new DefDef(mods, name, tparams, vparamss, tpt, rhs).copyAttrs(tree)
- def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) =
- new TypeDef(mods, name.toTypeName, tparams, rhs).copyAttrs(tree)
- def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) =
- new LabelDef(name, params, rhs).copyAttrs(tree)
- def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) =
- new Import(expr, selectors).copyAttrs(tree)
- def DocDef(tree: Tree, comment: DocComment, definition: Tree) =
- new DocDef(comment, definition).copyAttrs(tree)
- def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) =
- new Template(parents, self, body).copyAttrs(tree)
- def Block(tree: Tree, stats: List[Tree], expr: Tree) =
- new Block(stats, expr).copyAttrs(tree)
- def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) =
- new CaseDef(pat, guard, body).copyAttrs(tree)
- def Alternative(tree: Tree, trees: List[Tree]) =
- new Alternative(trees).copyAttrs(tree)
- def Star(tree: Tree, elem: Tree) =
- new Star(elem).copyAttrs(tree)
- def Bind(tree: Tree, name: Name, body: Tree) =
- new Bind(name, body).copyAttrs(tree)
- def UnApply(tree: Tree, fun: Tree, args: List[Tree]) =
- new UnApply(fun, args).copyAttrs(tree)
- def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) =
- new ArrayValue(elemtpt, trees).copyAttrs(tree)
- def Function(tree: Tree, vparams: List[ValDef], body: Tree) =
- new Function(vparams, body).copyAttrs(tree)
- def Assign(tree: Tree, lhs: Tree, rhs: Tree) =
- new Assign(lhs, rhs).copyAttrs(tree)
- def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) =
- new AssignOrNamedArg(lhs, rhs).copyAttrs(tree)
- def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) =
- new If(cond, thenp, elsep).copyAttrs(tree)
- def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) =
- new Match(selector, cases).copyAttrs(tree)
- def Return(tree: Tree, expr: Tree) =
- new Return(expr).copyAttrs(tree)
- def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) =
- new Try(block, catches, finalizer).copyAttrs(tree)
- def Throw(tree: Tree, expr: Tree) =
- new Throw(expr).copyAttrs(tree)
- def New(tree: Tree, tpt: Tree) =
- new New(tpt).copyAttrs(tree)
- def Typed(tree: Tree, expr: Tree, tpt: Tree) =
- new Typed(expr, tpt).copyAttrs(tree)
- def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) =
- new TypeApply(fun, args).copyAttrs(tree)
- def Apply(tree: Tree, fun: Tree, args: List[Tree]) =
- (tree match {
- case _: ApplyToImplicitArgs => new ApplyToImplicitArgs(fun, args)
- case _: ApplyImplicitView => new ApplyImplicitView(fun, args)
- case _ => new Apply(fun, args)
- }).copyAttrs(tree)
- def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) =
- new ApplyDynamic(qual, args).copyAttrs(tree)
- def Super(tree: Tree, qual: Tree, mix: TypeName) =
- new Super(qual, mix).copyAttrs(tree)
- def This(tree: Tree, qual: Name) =
- new This(qual.toTypeName).copyAttrs(tree)
- def Select(tree: Tree, qualifier: Tree, selector: Name) =
- new Select(qualifier, selector).copyAttrs(tree)
- def Ident(tree: Tree, name: Name) =
- new Ident(name).copyAttrs(tree)
- def Literal(tree: Tree, value: Constant) =
- new Literal(value).copyAttrs(tree)
- def TypeTree(tree: Tree) =
- new TypeTree().copyAttrs(tree)
- def TypeTreeWithDeferredRefCheck(tree: Tree) = tree match {
- case dc@TypeTreeWithDeferredRefCheck() => new TypeTreeWithDeferredRefCheck()(dc.check).copyAttrs(tree)
- }
- def Annotated(tree: Tree, annot: Tree, arg: Tree) =
- new Annotated(annot, arg).copyAttrs(tree)
- def SingletonTypeTree(tree: Tree, ref: Tree) =
- new SingletonTypeTree(ref).copyAttrs(tree)
- def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) =
- new SelectFromTypeTree(qualifier, selector.toTypeName).copyAttrs(tree)
- def CompoundTypeTree(tree: Tree, templ: Template) =
- new CompoundTypeTree(templ).copyAttrs(tree)
- def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) =
- new AppliedTypeTree(tpt, args).copyAttrs(tree)
- def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) =
- new TypeBoundsTree(lo, hi).copyAttrs(tree)
- def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) =
- new ExistentialTypeTree(tpt, whereClauses).copyAttrs(tree)
- def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) =
- new SelectFromArray(qualifier, selector, erasure).copyAttrs(tree)
- }
-
- class LazyTreeCopier(treeCopy: TreeCopier) extends TreeCopier {
- def this() = this(new StrictTreeCopier)
- def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) = tree match {
- case t @ ClassDef(mods0, name0, tparams0, impl0)
- if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (impl0 == impl) => t
- case _ => treeCopy.ClassDef(tree, mods, name, tparams, impl)
- }
- def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) = tree match {
- case t @ PackageDef(pid0, stats0)
- if (pid0 == pid) && (stats0 == stats) => t
- case _ => treeCopy.PackageDef(tree, pid, stats)
- }
- def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = tree match {
- case t @ ModuleDef(mods0, name0, impl0)
- if (mods0 == mods) && (name0 == name) && (impl0 == impl) => t
- case _ => treeCopy.ModuleDef(tree, mods, name, impl)
- }
- def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) = tree match {
- case t @ ValDef(mods0, name0, tpt0, rhs0)
- if (mods0 == mods) && (name0 == name) && (tpt0 == tpt) && (rhs0 == rhs) => t
- case _ => treeCopy.ValDef(tree, mods, name, tpt, rhs)
- }
- def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = tree match {
- case t @ DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0)
- if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) &&
- (vparamss0 == vparamss) && (tpt0 == tpt) && (rhs == rhs0) => t
- case _ => treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs)
- }
- def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) = tree match {
- case t @ TypeDef(mods0, name0, tparams0, rhs0)
- if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (rhs0 == rhs) => t
- case _ => treeCopy.TypeDef(tree, mods, name, tparams, rhs)
- }
- def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = tree match {
- case t @ LabelDef(name0, params0, rhs0)
- if (name0 == name) && (params0 == params) && (rhs0 == rhs) => t
- case _ => treeCopy.LabelDef(tree, name, params, rhs)
- }
- def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = tree match {
- case t @ Import(expr0, selectors0)
- if (expr0 == expr) && (selectors0 == selectors) => t
- case _ => treeCopy.Import(tree, expr, selectors)
- }
- def DocDef(tree: Tree, comment: DocComment, definition: Tree) = tree match {
- case t @ DocDef(comment0, definition0)
- if (comment0 == comment) && (definition0 == definition) => t
- case _ => treeCopy.DocDef(tree, comment, definition)
- }
- def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) = tree match {
- case t @ Template(parents0, self0, body0)
- if (parents0 == parents) && (self0 == self) && (body0 == body) => t
- case _ => treeCopy.Template(tree, parents, self, body)
- }
- def Block(tree: Tree, stats: List[Tree], expr: Tree) = tree match {
- case t @ Block(stats0, expr0)
- if ((stats0 == stats) && (expr0 == expr)) => t
- case _ => treeCopy.Block(tree, stats, expr)
- }
- def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = tree match {
- case t @ CaseDef(pat0, guard0, body0)
- if (pat0 == pat) && (guard0 == guard) && (body0 == body) => t
- case _ => treeCopy.CaseDef(tree, pat, guard, body)
- }
- def Alternative(tree: Tree, trees: List[Tree]) = tree match {
- case t @ Alternative(trees0)
- if trees0 == trees => t
- case _ => treeCopy.Alternative(tree, trees)
- }
- def Star(tree: Tree, elem: Tree) = tree match {
- case t @ Star(elem0)
- if elem0 == elem => t
- case _ => treeCopy.Star(tree, elem)
- }
- def Bind(tree: Tree, name: Name, body: Tree) = tree match {
- case t @ Bind(name0, body0)
- if (name0 == name) && (body0 == body) => t
- case _ => treeCopy.Bind(tree, name, body)
- }
- def UnApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
- case t @ UnApply(fun0, args0)
- if (fun0 == fun) && (args0 == args) => t
- case _ => treeCopy.UnApply(tree, fun, args)
- }
- def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) = tree match {
- case t @ ArrayValue(elemtpt0, trees0)
- if (elemtpt0 == elemtpt) && (trees0 == trees) => t
- case _ => treeCopy.ArrayValue(tree, elemtpt, trees)
- }
- def Function(tree: Tree, vparams: List[ValDef], body: Tree) = tree match {
- case t @ Function(vparams0, body0)
- if (vparams0 == vparams) && (body0 == body) => t
- case _ => treeCopy.Function(tree, vparams, body)
- }
- def Assign(tree: Tree, lhs: Tree, rhs: Tree) = tree match {
- case t @ Assign(lhs0, rhs0)
- if (lhs0 == lhs) && (rhs0 == rhs) => t
- case _ => treeCopy.Assign(tree, lhs, rhs)
- }
- def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = tree match {
- case t @ AssignOrNamedArg(lhs0, rhs0)
- if (lhs0 == lhs) && (rhs0 == rhs) => t
- case _ => treeCopy.AssignOrNamedArg(tree, lhs, rhs)
- }
- def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = tree match {
- case t @ If(cond0, thenp0, elsep0)
- if (cond0 == cond) && (thenp0 == thenp) && (elsep0 == elsep) => t
- case _ => treeCopy.If(tree, cond, thenp, elsep)
- }
- def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = tree match {
- case t @ Match(selector0, cases0)
- if (selector0 == selector) && (cases0 == cases) => t
- case _ => treeCopy.Match(tree, selector, cases)
- }
- def Return(tree: Tree, expr: Tree) = tree match {
- case t @ Return(expr0)
- if expr0 == expr => t
- case _ => treeCopy.Return(tree, expr)
- }
- def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = tree match {
- case t @ Try(block0, catches0, finalizer0)
- if (block0 == block) && (catches0 == catches) && (finalizer0 == finalizer) => t
- case _ => treeCopy.Try(tree, block, catches, finalizer)
- }
- def Throw(tree: Tree, expr: Tree) = tree match {
- case t @ Throw(expr0)
- if expr0 == expr => t
- case _ => treeCopy.Throw(tree, expr)
- }
- def New(tree: Tree, tpt: Tree) = tree match {
- case t @ New(tpt0)
- if tpt0 == tpt => t
- case _ => treeCopy.New(tree, tpt)
- }
- def Typed(tree: Tree, expr: Tree, tpt: Tree) = tree match {
- case t @ Typed(expr0, tpt0)
- if (expr0 == expr) && (tpt0 == tpt) => t
- case _ => treeCopy.Typed(tree, expr, tpt)
- }
- def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
- case t @ TypeApply(fun0, args0)
- if (fun0 == fun) && (args0 == args) => t
- case _ => treeCopy.TypeApply(tree, fun, args)
- }
- def Apply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
- case t @ Apply(fun0, args0)
- if (fun0 == fun) && (args0 == args) => t
- case _ => treeCopy.Apply(tree, fun, args)
- }
- def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = tree match {
- case t @ ApplyDynamic(qual0, args0)
- if (qual0 == qual) && (args0 == args) => t
- case _ => treeCopy.ApplyDynamic(tree, qual, args)
- }
- def Super(tree: Tree, qual: Tree, mix: TypeName) = tree match {
- case t @ Super(qual0, mix0)
- if (qual0 == qual) && (mix0 == mix) => t
- case _ => treeCopy.Super(tree, qual, mix)
- }
- def This(tree: Tree, qual: Name) = tree match {
- case t @ This(qual0)
- if qual0 == qual => t
- case _ => treeCopy.This(tree, qual)
- }
- def Select(tree: Tree, qualifier: Tree, selector: Name) = tree match {
- case t @ Select(qualifier0, selector0)
- if (qualifier0 == qualifier) && (selector0 == selector) => t
- case _ => treeCopy.Select(tree, qualifier, selector)
- }
- def Ident(tree: Tree, name: Name) = tree match {
- case t @ Ident(name0)
- if name0 == name => t
- case _ => treeCopy.Ident(tree, name)
- }
- def Literal(tree: Tree, value: Constant) = tree match {
- case t @ Literal(value0)
- if value0 == value => t
- case _ => treeCopy.Literal(tree, value)
- }
- def TypeTree(tree: Tree) = tree match {
- case t @ TypeTree() => t
- case _ => treeCopy.TypeTree(tree)
- }
- def TypeTreeWithDeferredRefCheck(tree: Tree) = tree match {
- case t @ TypeTreeWithDeferredRefCheck() => t
- case _ => treeCopy.TypeTreeWithDeferredRefCheck(tree)
- }
- def Annotated(tree: Tree, annot: Tree, arg: Tree) = tree match {
- case t @ Annotated(annot0, arg0)
- if (annot0==annot) => t
- case _ => treeCopy.Annotated(tree, annot, arg)
- }
- def SingletonTypeTree(tree: Tree, ref: Tree) = tree match {
- case t @ SingletonTypeTree(ref0)
- if ref0 == ref => t
- case _ => treeCopy.SingletonTypeTree(tree, ref)
- }
- def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = tree match {
- case t @ SelectFromTypeTree(qualifier0, selector0)
- if (qualifier0 == qualifier) && (selector0 == selector) => t
- case _ => treeCopy.SelectFromTypeTree(tree, qualifier, selector)
- }
- def CompoundTypeTree(tree: Tree, templ: Template) = tree match {
- case t @ CompoundTypeTree(templ0)
- if templ0 == templ => t
- case _ => treeCopy.CompoundTypeTree(tree, templ)
- }
- def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = tree match {
- case t @ AppliedTypeTree(tpt0, args0)
- if (tpt0 == tpt) && (args0 == args) => t
- case _ => treeCopy.AppliedTypeTree(tree, tpt, args)
- }
- def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = tree match {
- case t @ TypeBoundsTree(lo0, hi0)
- if (lo0 == lo) && (hi0 == hi) => t
- case _ => treeCopy.TypeBoundsTree(tree, lo, hi)
- }
- def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = tree match {
- case t @ ExistentialTypeTree(tpt0, whereClauses0)
- if (tpt0 == tpt) && (whereClauses0 == whereClauses) => t
- case _ => treeCopy.ExistentialTypeTree(tree, tpt, whereClauses)
- }
- def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) = tree match {
- case t @ SelectFromArray(qualifier0, selector0, _)
- if (qualifier0 == qualifier) && (selector0 == selector) => t
- case _ => treeCopy.SelectFromArray(tree, qualifier, selector, erasure)
- }
- }
-
- abstract class Transformer {
- val treeCopy: TreeCopier = new LazyTreeCopier
- protected var currentOwner: Symbol = definitions.RootClass
- protected def currentMethod = currentOwner.enclMethod
- protected def currentClass = currentOwner.enclClass
- protected def currentPackage = currentOwner.toplevelClass.owner
- def transform(tree: Tree): Tree = tree match {
- case EmptyTree =>
- tree
- case PackageDef(pid, stats) =>
- treeCopy.PackageDef(
- tree, transform(pid).asInstanceOf[RefTree],
- atOwner(tree.symbol.moduleClass) {
- transformStats(stats, currentOwner)
- }
- )
- case ClassDef(mods, name, tparams, impl) =>
- atOwner(tree.symbol) {
- treeCopy.ClassDef(tree, transformModifiers(mods), name,
- transformTypeDefs(tparams), transformTemplate(impl))
- }
- case ModuleDef(mods, name, impl) =>
- atOwner(tree.symbol.moduleClass) {
- treeCopy.ModuleDef(tree, transformModifiers(mods),
- name, transformTemplate(impl))
- }
- case ValDef(mods, name, tpt, rhs) =>
- atOwner(tree.symbol) {
- treeCopy.ValDef(tree, transformModifiers(mods),
- name, transform(tpt), transform(rhs))
- }
- case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- atOwner(tree.symbol) {
- treeCopy.DefDef(tree, transformModifiers(mods), name,
- transformTypeDefs(tparams), transformValDefss(vparamss),
- transform(tpt), transform(rhs))
- }
- case TypeDef(mods, name, tparams, rhs) =>
- atOwner(tree.symbol) {
- treeCopy.TypeDef(tree, transformModifiers(mods), name,
- transformTypeDefs(tparams), transform(rhs))
- }
- case LabelDef(name, params, rhs) =>
- treeCopy.LabelDef(tree, name, transformIdents(params), transform(rhs)) //bq: Martin, once, atOwner(...) works, also change `LamdaLifter.proxy'
- case Import(expr, selectors) =>
- treeCopy.Import(tree, transform(expr), selectors)
- case DocDef(comment, definition) =>
- treeCopy.DocDef(tree, comment, transform(definition))
- case Template(parents, self, body) =>
- treeCopy.Template(tree, transformTrees(parents), transformValDef(self), transformStats(body, tree.symbol))
- case Block(stats, expr) =>
- treeCopy.Block(tree, transformStats(stats, currentOwner), transform(expr))
- case CaseDef(pat, guard, body) =>
- treeCopy.CaseDef(tree, transform(pat), transform(guard), transform(body))
- case Alternative(trees) =>
- treeCopy.Alternative(tree, transformTrees(trees))
- case Star(elem) =>
- treeCopy.Star(tree, transform(elem))
- case Bind(name, body) =>
- treeCopy.Bind(tree, name, transform(body))
- case UnApply(fun, args) =>
- treeCopy.UnApply(tree, fun, transformTrees(args)) // bq: see test/.../unapplyContexts2.scala
- case ArrayValue(elemtpt, trees) =>
- treeCopy.ArrayValue(tree, transform(elemtpt), transformTrees(trees))
- case Function(vparams, body) =>
- atOwner(tree.symbol) {
- treeCopy.Function(tree, transformValDefs(vparams), transform(body))
- }
- case Assign(lhs, rhs) =>
- treeCopy.Assign(tree, transform(lhs), transform(rhs))
- case AssignOrNamedArg(lhs, rhs) =>
- treeCopy.AssignOrNamedArg(tree, transform(lhs), transform(rhs))
- case If(cond, thenp, elsep) =>
- treeCopy.If(tree, transform(cond), transform(thenp), transform(elsep))
- case Match(selector, cases) =>
- treeCopy.Match(tree, transform(selector), transformCaseDefs(cases))
- case Return(expr) =>
- treeCopy.Return(tree, transform(expr))
- case Try(block, catches, finalizer) =>
- treeCopy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer))
- case Throw(expr) =>
- treeCopy.Throw(tree, transform(expr))
- case New(tpt) =>
- treeCopy.New(tree, transform(tpt))
- case Typed(expr, tpt) =>
- treeCopy.Typed(tree, transform(expr), transform(tpt))
- case TypeApply(fun, args) =>
- treeCopy.TypeApply(tree, transform(fun), transformTrees(args))
- case Apply(fun, args) =>
- treeCopy.Apply(tree, transform(fun), transformTrees(args))
- case ApplyDynamic(qual, args) =>
- treeCopy.ApplyDynamic(tree, transform(qual), transformTrees(args))
- case Super(qual, mix) =>
- treeCopy.Super(tree, transform(qual), mix)
- case This(qual) =>
- treeCopy.This(tree, qual)
- case Select(qualifier, selector) =>
- treeCopy.Select(tree, transform(qualifier), selector)
- case Ident(name) =>
- treeCopy.Ident(tree, name)
- case Literal(value) =>
- treeCopy.Literal(tree, value)
- case TypeTree() =>
- treeCopy.TypeTree(tree)
- case TypeTreeWithDeferredRefCheck() =>
- treeCopy.TypeTreeWithDeferredRefCheck(tree)
- case Annotated(annot, arg) =>
- treeCopy.Annotated(tree, transform(annot), transform(arg))
- case SingletonTypeTree(ref) =>
- treeCopy.SingletonTypeTree(tree, transform(ref))
- case SelectFromTypeTree(qualifier, selector) =>
- treeCopy.SelectFromTypeTree(tree, transform(qualifier), selector)
- case CompoundTypeTree(templ) =>
- treeCopy.CompoundTypeTree(tree, transformTemplate(templ))
- case AppliedTypeTree(tpt, args) =>
- treeCopy.AppliedTypeTree(tree, transform(tpt), transformTrees(args))
- case TypeBoundsTree(lo, hi) =>
- treeCopy.TypeBoundsTree(tree, transform(lo), transform(hi))
- case ExistentialTypeTree(tpt, whereClauses) =>
- treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses))
- case SelectFromArray(qualifier, selector, erasure) =>
- treeCopy.SelectFromArray(tree, transform(qualifier), selector, erasure)
- }
-
- def transformTrees(trees: List[Tree]): List[Tree] =
- trees mapConserve (transform(_))
- def transformTemplate(tree: Template): Template =
- transform(tree: Tree).asInstanceOf[Template]
- def transformTypeDefs(trees: List[TypeDef]): List[TypeDef] =
- trees mapConserve (tree => transform(tree).asInstanceOf[TypeDef])
- def transformValDef(tree: ValDef): ValDef =
- if (tree.isEmpty) tree else transform(tree).asInstanceOf[ValDef]
- def transformValDefs(trees: List[ValDef]): List[ValDef] =
- trees mapConserve (transformValDef(_))
- def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] =
- treess mapConserve (transformValDefs(_))
- def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] =
- trees mapConserve (tree => transform(tree).asInstanceOf[CaseDef])
- def transformIdents(trees: List[Ident]): List[Ident] =
- trees mapConserve (tree => transform(tree).asInstanceOf[Ident])
- def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
- stats mapConserve (stat =>
- if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat))
- else transform(stat)) filter (EmptyTree !=)
+ class Transformer extends super.Transformer {
def transformUnit(unit: CompilationUnit) { unit.body = transform(unit.body) }
- def transformModifiers(mods: Modifiers): Modifiers =
- Modifiers(mods.flags, mods.privateWithin, transformTrees(mods.annotations), mods.positions)
-
- def atOwner[A](owner: Symbol)(trans: => A): A = {
- val prevOwner = currentOwner
- currentOwner = owner
- val result = trans
- currentOwner = prevOwner
- result
- }
- }
-
- class Traverser extends super.Traverser {
- /** Compiler specific tree types are handled here: the remainder are in
- * the library's abstract tree traverser.
- */
- override def traverse(tree: Tree): Unit = tree match {
- case AssignOrNamedArg(lhs, rhs) =>
- traverse(lhs); traverse(rhs)
- case DocDef(comment, definition) =>
- traverse(definition)
- case Parens(ts) =>
- traverseTrees(ts)
- case TypeTreeWithDeferredRefCheck() => // TODO: should we traverse the wrapped tree?
- // (and rewrap the result? how to update the deferred check? would need to store wrapped tree instead of returning it from check)
- case Super(qual, _) =>
- traverse(qual) // !!! remove when Super is done
- case _ => super.traverse(tree)
- }
-
- /** The abstract traverser is not aware of Tree.isTerm, so we override this one.
- */
- override def traverseStats(stats: List[Tree], exprOwner: Symbol) {
- stats foreach (stat =>
- if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(traverse(stat))
- else traverse(stat)
- )
- }
-
- /** Leave apply available in the generic traverser to do something else.
- */
- def apply[T <: Tree](tree: T): T = { traverse(tree); tree }
}
-
- private lazy val duplicator = new Transformer {
- override val treeCopy = new StrictTreeCopier
- override def transform(t: Tree) = {
- val t1 = super.transform(t)
- if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus
- t1
- }
- }
-
- private class ShallowDuplicator(orig: Tree) extends Transformer {
- override val treeCopy = new StrictTreeCopier
- override def transform(tree: Tree) =
- if (tree eq orig) super.transform(tree)
- else tree
- }
-
- class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer {
- override def transform(tree: Tree): Tree = tree match {
- case Ident(_) =>
- def subst(from: List[Symbol], to: List[Tree]): Tree =
- if (from.isEmpty) tree
- else if (tree.symbol == from.head) to.head
- else subst(from.tail, to.tail);
- subst(from, to)
- case _ =>
- super.transform(tree)
- }
- }
-
- class TreeTypeSubstituter(val from: List[Symbol], val to: List[Type]) extends Traverser {
- val typeSubst = new SubstTypeMap(from, to)
- def fromContains = typeSubst.fromContains
-
- override def traverse(tree: Tree) {
- if (tree.tpe ne null) tree.tpe = typeSubst(tree.tpe)
- if (tree.isDef) {
- val sym = tree.symbol
- val info1 = typeSubst(sym.info)
- if (info1 ne sym.info) sym.setInfo(info1)
- }
- super.traverse(tree)
- }
- override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate)
- override def toString() = "TreeTypeSubstituter("+from+","+to+")"
- }
-
- lazy val EmptyTreeTypeSubstituter = new TreeTypeSubstituter(List(), List())
-
- class TreeSymSubstTraverser(val from: List[Symbol], val to: List[Symbol]) extends Traverser {
- val subst = new SubstSymMap(from, to)
- override def traverse(tree: Tree) {
- if (tree.tpe ne null) tree.tpe = subst(tree.tpe)
- if (tree.isDef) {
- val sym = tree.symbol
- val info1 = subst(sym.info)
- if (info1 ne sym.info) sym.setInfo(info1)
- }
- super.traverse(tree)
- }
- override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate)
- override def toString() = "TreeSymSubstTraverser("+from+","+to+")"
- }
-
- /** Substitute symbols in 'from' with symbols in 'to'. Returns a new
- * tree using the new symbols and whose Ident and Select nodes are
- * name-consistent with the new symbols.
- */
- class TreeSymSubstituter(from: List[Symbol], to: List[Symbol]) extends Transformer {
- val symSubst = new SubstSymMap(from, to)
- override def transform(tree: Tree): Tree = {
- def subst(from: List[Symbol], to: List[Symbol]) {
- if (!from.isEmpty)
- if (tree.symbol == from.head) tree setSymbol to.head
- else subst(from.tail, to.tail)
- }
-
- if (tree.tpe ne null) tree.tpe = symSubst(tree.tpe)
- if (tree.hasSymbol) {
- subst(from, to)
- tree match {
- case Ident(name0) if tree.symbol != NoSymbol =>
- treeCopy.Ident(tree, tree.symbol.name)
- case Select(qual, name0) =>
- treeCopy.Select(tree, transform(qual), tree.symbol.name)
- case _ =>
- super.transform(tree)
- }
- } else
- super.transform(tree)
- }
- def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T]
- override def toString() = "TreeSymSubstituter("+from+","+to+")"
- }
-
- class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser {
- def changeOwner(tree: Tree) = {
- if ((tree.isDef || tree.isInstanceOf[Function]) &&
- tree.symbol != NoSymbol && tree.symbol.owner == oldowner)
- tree.symbol.owner = newowner
- }
- override def traverse(tree: Tree) {
- changeOwner(tree)
- super.traverse(tree)
- }
- }
-
- object posAssigner extends Traverser {
- var pos: Position = _
- override def traverse(t: Tree) {
- if (t != EmptyTree && t.pos == NoPosition) {
- t.setPos(pos)
- super.traverse(t)
- }
- }
- }
-
- def atPos[T <: Tree](pos: Position)(tree: T): T = {
- posAssigner.pos = pos
- posAssigner.traverse(tree)
- tree
- }
-
- class ForeachPartialTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser {
- override def traverse(tree: Tree) {
- val t = if (pf isDefinedAt tree) pf(tree) else tree
- super.traverse(t)
- }
- }
-
- class ForeachTreeTraverser(f: Tree => Unit) extends Traverser {
- override def traverse(t: Tree) {
- f(t)
- super.traverse(t)
- }
- }
-
- class FilterTreeTraverser(p: Tree => Boolean) extends Traverser {
- val hits = new ListBuffer[Tree]
- override def traverse(t: Tree) {
- if (p(t)) hits += t
- super.traverse(t)
- }
- }
-
- class FindTreeTraverser(p: Tree => Boolean) extends Traverser {
- var result: Option[Tree] = None
- override def traverse(t: Tree) {
- if (result.isEmpty) {
- if (p(t)) result = Some(t)
- super.traverse(t)
- }
- }
- }
-
- object resetPos extends Traverser {
- override def traverse(t: Tree) {
- if (t != EmptyTree) t.setPos(NoPosition)
- super.traverse(t)
- }
- }
-
-
- /** resets symbol and tpe fields in a tree, @see ResetAttrsTraverse
- */
- def resetAllAttrs[A<:Tree](x:A): A = { new ResetAttrsTraverser().traverse(x); x }
- def resetLocalAttrs[A<:Tree](x:A): A = { new ResetLocalAttrsTraverser().traverse(x); x }
-
- /** A traverser which resets symbol and tpe fields of all nodes in a given tree
- * except for (1) TypeTree nodes, whose <code>.tpe</code> field is kept, and
- * (2) This(pkg) nodes, where pkg refers to a package symbol -- their attributes are kept, and
- * (3) if a <code>.symbol</code> field refers to a symbol which is defined
- * outside the tree, it is also kept.
- *
- * (2) is necessary because some This(pkg) are generated where pkg is not
- * an enclosing package.n In that case, resetting the symbol would cause the
- * next type checking run to fail. See #3152.
- *
- * (bq:) This traverser has mutable state and should be discarded after use
- */
- private class ResetAttrsTraverser extends Traverser {
- protected def isLocal(sym: Symbol): Boolean = true
- protected def resetDef(tree: Tree) {
- tree.symbol = NoSymbol
- }
- override def traverse(tree: Tree): Unit = {
- tree match {
- case _: DefTree | Function(_, _) | Template(_, _, _) =>
- resetDef(tree)
- tree.tpe = null
- case tpt: TypeTree =>
- if (tpt.wasEmpty) tree.tpe = null
- case This(_) if tree.symbol != null && tree.symbol.isPackageClass =>
- ;
- case EmptyTree =>
- ;
- case _ =>
- if (tree.hasSymbol && isLocal(tree.symbol)) tree.symbol = NoSymbol
- tree.tpe = null
- }
- super.traverse(tree)
- }
- }
-
- private class ResetLocalAttrsTraverser extends ResetAttrsTraverser {
- private val erasedSyms = HashSet[Symbol](8)
- override protected def isLocal(sym: Symbol) = erasedSyms(sym)
- override protected def resetDef(tree: Tree) {
- erasedSyms addEntry tree.symbol
- super.resetDef(tree)
- }
- override def traverse(tree: Tree): Unit = tree match {
- case Template(parents, self, body) =>
- for (stat <- body)
- if (stat.isDef) erasedSyms.addEntry(stat.symbol)
- super.traverse(tree)
- case _ =>
- super.traverse(tree)
- }
- }
-}
-
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index a3fd44fa47..fa81c3f033 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -12,7 +12,7 @@ import scala.util.control.ControlThrowable
import scala.tools.nsc.util.{SourceFile,CharArrayReader}
import scala.xml.{ Text, TextBuffer }
import scala.xml.Utility.{ isNameStart, isNameChar, isSpace }
-import util.Chars.{ SU, LF }
+import scala.reflect.Chars.{ SU, LF }
// XXX/Note: many/most of the functions in here are almost direct cut and pastes
// from another file - scala.xml.parsing.MarkupParser, it looks like.
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 086b72be56..e1d45ac8ca 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -11,9 +11,9 @@ package ast.parser
import scala.collection.mutable.ListBuffer
import util.{ SourceFile, OffsetPosition, FreshNameCreator }
-import scala.reflect.generic.{ ModifierFlags => Flags }
+import scala.reflect.common.{ ModifierFlags => Flags }
import Tokens._
-import util.Chars.{ isScalaLetter }
+import scala.reflect.Chars.{ isScalaLetter }
/** Historical note: JavaParsers started life as a direct copy of Parsers
* but at a time when that Parsers had been replaced by a different one.
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
index 528705b03d..aa862653d6 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
@@ -28,7 +28,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
var isPattern: Boolean = _
- trait XMLTypeNames extends LibraryTypeNames {
+ trait XMLTypeNames extends TypeNames {
val _Comment: NameType = "Comment"
val _Elem: NameType = "Elem"
val _EntityRef: NameType = "EntityRef"
@@ -43,7 +43,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
val _UnprefixedAttribute: NameType = "UnprefixedAttribute"
}
- trait XMLTermNames extends LibraryTermNames {
+ trait XMLTermNames extends TermNames {
val _Null: NameType = "Null"
val __Elem: NameType = "Elem"
val __Text: NameType = "Text"
@@ -63,8 +63,11 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
type NameType = TermName
implicit def createNameType(name: String): TermName = newTermName(name)
}
- import xmltypes._
- import xmlterms._
+
+ import xmltypes.{_Comment, _Elem, _EntityRef, _Group, _MetaData, _NamespaceBinding, _NodeBuffer,
+ _PrefixedAttribute, _ProcInstr, _Text, _Unparsed, _UnprefixedAttribute}
+
+ import xmlterms.{_Null, __Elem, __Text, _buf, _md, _plus, _scope, _tmpscope, _xml}
// convenience methods
private def LL[A](x: A*): List[List[A]] = List(List(x:_*))
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
index 2f0d86c993..fb3d79a3c7 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
@@ -8,7 +8,7 @@ package backend.jvm
import ch.epfl.lamp.fjbg._
import java.io.{ DataOutputStream, OutputStream }
-import scala.tools.nsc.io.{ AbstractFile, Path }
+import scala.tools.nsc.io.Path
import scala.tools.nsc.util.ScalaClassLoader
import scala.tools.util.Javap
import java.util.jar.{ JarEntry, JarOutputStream }
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 76e0162593..4c584cd4b5 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -10,9 +10,8 @@ package backend.jvm
import java.io.{ DataOutputStream, OutputStream }
import java.nio.ByteBuffer
import scala.collection.{ mutable, immutable }
-import scala.reflect.generic.{ PickleFormat, PickleBuffer }
+import scala.reflect.common.pickling.{ PickleFormat, PickleBuffer }
import scala.tools.reflect.SigParser
-import scala.tools.nsc.io.{ AbstractFile, Path }
import scala.tools.nsc.util.ScalaClassLoader
import scala.tools.nsc.symtab._
import scala.tools.nsc.symtab.classfile.ClassfileConstants._
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index 1968ca56aa..7abba299b5 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -24,6 +24,8 @@ abstract class GenMSIL extends SubComponent {
import icodes._
import icodes.opcodes._
+ val x = loaders
+
/** Create a new phase */
override def newPhase(p: Phase) = new MsilPhase(p)
diff --git a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
index b2a93873b0..41eb01704f 100644
--- a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
@@ -2,7 +2,7 @@ package scala.tools.nsc
package dependencies
import util.SourceFile
-import io.{ AbstractFile, Path }
+import io.Path
import collection._
import symtab.Flags
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index ba15ea8aed..ac31b20aa5 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -66,11 +66,11 @@ trait CompilerControl { self: Global =>
* if it does not yet exist create a new one atomically
* Note: We want to get roid of this operation as it messes compiler invariants.
*/
- @deprecated("use getUnitOf(s) or onUnitOf(s) instead", "2.9.0")
+ @deprecated("use getUnitOf(s) or onUnitOf(s) instead")
def unitOf(s: SourceFile): RichCompilationUnit = getOrCreateUnitOf(s)
/** The compilation unit corresponding to a position */
- @deprecated("use getUnitOf(pos.source) or onUnitOf(pos.source) instead", "2.9.0")
+ @deprecated("use getUnitOf(pos.source) or onUnitOf(pos.source) instead")
def unitOf(pos: Position): RichCompilationUnit = getOrCreateUnitOf(pos.source)
/** Removes the CompilationUnit corresponding to the given SourceFile
@@ -211,7 +211,7 @@ trait CompilerControl { self: Global =>
/** Tells the compile server to shutdown, and not to restart again */
def askShutdown() = scheduler raise ShutdownReq
- @deprecated("use parseTree(source) instead", "2.9.0")
+ @deprecated("use parseTree(source) instead") // deleted 2nd parameter, as thius has to run on 2.8 also.
def askParse(source: SourceFile, response: Response[Tree]) = respond(response) {
parseTree(source)
}
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index da97e10584..694df32e32 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -20,7 +20,7 @@ import scala.tools.nsc.ast._
import scala.tools.nsc.io.Pickler._
import scala.tools.nsc.typechecker.DivergentImplicit
import scala.annotation.tailrec
-import scala.reflect.generic.Flags.{ACCESSOR, PARAMACCESSOR}
+import symtab.Flags.{ACCESSOR, PARAMACCESSOR}
/** The main class of the presentation compiler in an interactive environment such as an IDE
*/
diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala
index 27947d5e0e..2690a6c79b 100644
--- a/src/compiler/scala/tools/nsc/interactive/REPL.scala
+++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala
@@ -60,7 +60,7 @@ object REPL {
def main(args: Array[String]) {
process(args)
- sys.exit(if (reporter.hasErrors) 1 else 0)
+ exit(if (reporter.hasErrors) 1 else 0)
}
def loop(action: (String) => Unit) {
@@ -134,7 +134,8 @@ object REPL {
doComplete(makePos(file, off1, off1))
case List("quit") =>
comp.askShutdown()
- sys.exit(1)
+ // deleted sys. as this has to run on 2.8 also
+ exit(1)
case List("structure", file) =>
doStructure(file)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
index 67cf037a3a..3a1a9d5bd9 100644
--- a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
+++ b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
@@ -113,8 +113,8 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
// See if we really have corresponding symbols, not just those
// which share the name
def isCorrespondingSym(from: Symbol, to: Symbol): Boolean =
- (from.hasTraitFlag == to.hasTraitFlag) &&
- (from.hasModuleFlag == to.hasModuleFlag)
+ (from.hasFlag(Flags.TRAIT) == to.hasFlag(Flags.TRAIT)) && // has to run in 2.8, so no hasTraitFlag
+ (from.hasFlag(Flags.MODULE) == to.hasFlag(Flags.MODULE))
// For testing purposes only, order irrelevant for compilation
def toStringSet(set: Set[AbstractFile]): String =
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 69858e8bba..fdf8f6bfab 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -10,10 +10,11 @@ import Predef.{ println => _, _ }
import java.io.{ PrintWriter }
import java.lang.reflect
import java.net.URL
-import util.{ Set => _, _ }
-import io.{ AbstractFile, VirtualDirectory }
+import util._
+import io.VirtualDirectory
import reporters.{ ConsoleReporter, Reporter }
-import symtab.{ Flags, Names }
+import symtab.Flags
+import scala.reflect.common.Names
import scala.tools.nsc.interpreter.{ Results => IR }
import scala.tools.util.PathResolver
import scala.tools.nsc.util.{ ScalaClassLoader, Exceptional }
diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
index e4921bd898..385e181404 100644
--- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
@@ -9,7 +9,7 @@ package interpreter
import scala.collection.{ mutable, immutable }
import scala.PartialFunction.cond
import scala.reflect.NameTransformer
-import util.Chars
+import scala.reflect.Chars
trait MemberHandlers {
val intp: IMain
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala b/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala
index cef46c963a..d14f4cefae 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala
@@ -9,7 +9,7 @@ package interpreter
import scala.collection.{ mutable, immutable }
import scala.PartialFunction.cond
import scala.reflect.NameTransformer
-import util.Chars
+import scala.reflect.Chars
trait ReplStrings {
// Longest common prefix
diff --git a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala
index 82e311028b..b87e556d7c 100644
--- a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala
@@ -13,7 +13,7 @@ import io.AbstractFile
* interchangeably. Except of course without the mutants.
*/
-trait AbsSettings {
+trait AbsSettings extends scala.reflect.common.settings.AbsSettings {
type Setting <: AbsSetting // Fix to the concrete Setting type
type ResultOfTryToSet // List[String] in mutable, (Settings, List[String]) in immutable
def errorFn: String => Unit
@@ -51,12 +51,6 @@ trait AbsSettings {
implicit lazy val SettingOrdering: Ordering[Setting] = Ordering.ordered
- trait AbsSettingValue {
- type T <: Any
- def value: T
- def isDefault: Boolean
- }
-
trait AbsSetting extends Ordered[Setting] with AbsSettingValue {
def name: String
def helpDescription: String
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
index 87398e4117..e38ccd2b80 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -15,7 +15,8 @@ import scala.io.Source
/** A mutable Settings object.
*/
-class MutableSettings(val errorFn: String => Unit) extends AbsSettings with ScalaSettings with Mutable {
+class MutableSettings(val errorFn: String => Unit) extends scala.reflect.common.settings.MutableSettings
+ with AbsSettings with ScalaSettings with Mutable {
type ResultOfTryToSet = List[String]
/** Iterates over the arguments applying them to settings where applicable.
@@ -201,21 +202,6 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal
}
def PrefixSetting(name: String, prefix: String, descr: String): PrefixSetting = add(new PrefixSetting(name, prefix, descr))
- // basically this is a value which remembers if it's been modified
- trait SettingValue extends AbsSettingValue {
- protected var v: T
- protected var setByUser: Boolean = false
- def postSetHook(): Unit
-
- def isDefault: Boolean = !setByUser
- def value: T = v
- def value_=(arg: T) = {
- setByUser = true
- v = arg
- postSetHook()
- }
- }
-
/** A class for holding mappings from source directories to
* their output location. This functionality can be accessed
* only programmatically. The command line compiler uses a
diff --git a/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala b/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala
index d26c5d65a0..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala
+++ b/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala
@@ -1,120 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2007-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-
-/** Additions to the type checker that can be added at
- * run time. Typically these are added by
- * compiler plugins. */
-trait AnnotationCheckers {
- self: SymbolTable =>
-
-
- /** An additional checker for annotations on types.
- * Typically these are registered by compiler plugins
- * with the addAnnotationChecker method. */
- abstract class AnnotationChecker {
- /** Check the annotations on two types conform. */
- def annotationsConform(tpe1: Type, tpe2: Type): Boolean
-
- /** Refine the computed least upper bound of a list of types.
- * All this should do is add annotations. */
- def annotationsLub(tp: Type, ts: List[Type]): Type = tp
-
- /** Refine the computed greatest lower bound of a list of types.
- * All this should do is add annotations. */
- def annotationsGlb(tp: Type, ts: List[Type]): Type = tp
-
- /** Refine the bounds on type parameters to the given type arguments. */
- def adaptBoundsToAnnotations(bounds: List[TypeBounds],
- tparams: List[Symbol], targs: List[Type]): List[TypeBounds] = bounds
-
- /** Modify the type that has thus far been inferred
- * for a tree. All this should do is add annotations. */
- def addAnnotations(tree: Tree, tpe: Type): Type = tpe
-
- /** Decide whether this annotation checker can adapt a tree
- * that has an annotated type to the given type tp, taking
- * into account the given mode (see method adapt in trait Typers).*/
- def canAdaptAnnotations(tree: Tree, mode: Int, pt: Type): Boolean = false
-
- /** Adapt a tree that has an annotated type to the given type tp,
- * taking into account the given mode (see method adapt in trait Typers).
- * An implementation cannot rely on canAdaptAnnotations being called
- * before. If the implementing class cannot do the adaptiong, it
- * should return the tree unchanged.*/
- def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = tree
- }
-
- /** The list of annotation checkers that have been registered */
- private var annotationCheckers: List[AnnotationChecker] = Nil
-
- /** Register an annotation checker. Typically these
- * are added by compiler plugins. */
- def addAnnotationChecker(checker: AnnotationChecker) {
- if (!(annotationCheckers contains checker))
- annotationCheckers = checker :: annotationCheckers
- }
-
- /** Remove all annotation checkers */
- def removeAllAnnotationCheckers() {
- annotationCheckers = Nil
- }
-
- /** Check that the annotations on two types conform. To do
- * so, consult all registered annotation checkers. */
- def annotationsConform(tp1: Type, tp2: Type): Boolean = {
- /* Finish quickly if there are no annotations */
- if (tp1.annotations.isEmpty && tp2.annotations.isEmpty)
- true
- else
- annotationCheckers.forall(
- _.annotationsConform(tp1,tp2))
- }
-
- /** Refine the computed least upper bound of a list of types.
- * All this should do is add annotations. */
- def annotationsLub(tpe: Type, ts: List[Type]): Type = {
- annotationCheckers.foldLeft(tpe)((tpe, checker) =>
- checker.annotationsLub(tpe, ts))
- }
-
- /** Refine the computed greatest lower bound of a list of types.
- * All this should do is add annotations. */
- def annotationsGlb(tpe: Type, ts: List[Type]): Type = {
- annotationCheckers.foldLeft(tpe)((tpe, checker) =>
- checker.annotationsGlb(tpe, ts))
- }
-
- /** Refine the bounds on type parameters to the given type arguments. */
- def adaptBoundsToAnnotations(bounds: List[TypeBounds],
- tparams: List[Symbol], targs: List[Type]): List[TypeBounds] = {
- annotationCheckers.foldLeft(bounds)((bounds, checker) =>
- checker.adaptBoundsToAnnotations(bounds, tparams, targs))
- }
-
- /** Let all annotations checkers add extra annotations
- * to this tree's type. */
- def addAnnotations(tree: Tree, tpe: Type): Type = {
- annotationCheckers.foldLeft(tpe)((tpe, checker) =>
- checker.addAnnotations(tree, tpe))
- }
-
- /** Find out whether any annotation checker can adapt a tree
- * to a given type. Called by Typers.adapt. */
- def canAdaptAnnotations(tree: Tree, mode: Int, pt: Type): Boolean = {
- annotationCheckers.exists(_.canAdaptAnnotations(tree, mode, pt))
- }
-
- /** Let registered annotation checkers adapt a tree
- * to a given type (called by Typers.adapt). Annotation checkers
- * that cannot do the adaption should pass the tree through
- * unchanged. */
- def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = {
- annotationCheckers.foldLeft(tree)((tree, checker) =>
- checker.adaptAnnotations(tree, mode, pt))
- }
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
index 3c67814346..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
+++ b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
@@ -1,152 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2007-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-
-import scala.tools.nsc.transform.Reifiers
-import util._
-
-/** AnnotationInfo and its helpers */
-trait AnnotationInfos extends reflect.generic.AnnotationInfos { self: SymbolTable =>
-
- /** Arguments to classfile annotations (which are written to
- * bytecode as java annotations) are either:
- * <ul>
- * <li>constants</li>
- * <li>arrays of constants</li>
- * <li>or nested classfile annotations</li>
- * </ul>
- */
- abstract class ClassfileAnnotArg
-
- /** Represents a compile-time Constant (Boolean, Byte, Short,
- * Char, Int, Long, Float, Double, String, java.lang.Class or
- * an instance of a Java enumeration value).
- */
- case class LiteralAnnotArg(const: Constant)
- extends ClassfileAnnotArg {
- override def toString = const.escapedStringValue
- }
-
- object LiteralAnnotArg extends LiteralAnnotArgExtractor
-
- /** Represents an array of classfile annotation arguments */
- case class ArrayAnnotArg(args: Array[ClassfileAnnotArg])
- extends ClassfileAnnotArg {
- override def toString = args.mkString("[", ", ", "]")
- }
-
- object ArrayAnnotArg extends ArrayAnnotArgExtractor
-
- /** A specific annotation argument that encodes an array of bytes as an array of `Long`. The type of the argument
- * declared in the annotation must be `String`. This specialised class is used to encode scala signatures for
- * reasons of efficiency, both in term of class-file size and in term of compiler performance. */
- case class ScalaSigBytes(bytes: Array[Byte]) extends ClassfileAnnotArg {
- override def toString = (bytes map { byte => (byte & 0xff).toHexString }).mkString("[ ", " ", " ]")
- lazy val encodedBytes =
- reflect.generic.ByteCodecs.encode(bytes)
- def isLong: Boolean = (encodedBytes.length > 65535)
- def sigAnnot: Type =
- if (this.isLong)
- definitions.ScalaLongSignatureAnnotation.tpe
- else
- definitions.ScalaSignatureAnnotation.tpe
- }
-
- /** Represents a nested classfile annotation */
- case class NestedAnnotArg(annInfo: AnnotationInfo)
- extends ClassfileAnnotArg {
- // The nested annotation should not have any Scala annotation arguments
- assert(annInfo.args.isEmpty, annInfo.args)
- override def toString = annInfo.toString
- }
-
- object NestedAnnotArg extends NestedAnnotArgExtractor
-
- class AnnotationInfoBase
-
- /** <p>
- * Typed information about an annotation. It can be attached to
- * either a symbol or an annotated type.
- * </p>
- * <p>
- * Annotations are written to the classfile as java annotations
- * if <code>atp</code> conforms to <code>ClassfileAnnotation</code>
- * (the classfile parser adds this interface to any Java annotation
- * class).
- * </p>
- * <p>
- * Annotations are pickled (written to scala symtab attribute
- * in the classfile) if <code>atp</code> inherits form
- * <code>StaticAnnotation</code>.
- * </p>
- * <p>
- * <code>args</code> stores arguments to Scala annotations,
- * represented as typed trees. Note that these trees are not
- * transformed by any phases following the type-checker.
- * </p>
- * <p>
- * <code>assocs</code> stores arguments to classfile annotations
- * as name-value pairs.
- * </p>
- */
- case class AnnotationInfo(atp: Type, args: List[Tree],
- assocs: List[(Name, ClassfileAnnotArg)])
- extends AnnotationInfoBase {
-
- // Classfile annot: args empty. Scala annot: assocs empty.
- assert(args.isEmpty || assocs.isEmpty)
-
- private var rawpos: Position = NoPosition
- def pos = rawpos
- def setPos(pos: Position): this.type = {
- rawpos = pos
- this
- }
-
- lazy val isTrivial: Boolean = atp.isTrivial && !(args exists (_.exists(_.isInstanceOf[This]))) // see annotationArgRewriter
-
- override def toString: String = atp +
- (if (!args.isEmpty) args.mkString("(", ", ", ")") else "") +
- (if (!assocs.isEmpty) (assocs map { case (x, y) => x+" = "+y } mkString ("(", ", ", ")")) else "")
-
- /** Check whether the type or any of the arguments are erroneous */
- def isErroneous = atp.isErroneous || args.exists(_.isErroneous)
-
- /** Check whether any of the arguments mention a symbol */
- def refsSymbol(sym: Symbol) =
- args.exists(_.exists(_.symbol == sym))
-
- /** Change all ident's with Symbol "from" to instead use symbol "to" */
- def substIdentSyms(from: Symbol, to: Symbol) = {
- val subs = new TreeSymSubstituter(List(from), List(to))
- AnnotationInfo(atp, args.map(subs(_)), assocs).setPos(pos)
- }
-
- // !!! when annotation arguments are not literal strings, but any sort of
- // assembly of strings, there is a fair chance they will turn up here not as
- // Literal(const) but some arbitrary AST.
- def stringArg(index: Int): Option[String] = if(args.size > index) Some(args(index) match {
- case Literal(const) => const.stringValue
- case x => x.toString // should not be necessary, but better than silently ignoring an issue
- }) else None
-
- def intArg(index: Int): Option[Int] = if(args.size > index) Some(args(index)) collect {
- case Literal(Constant(x: Int)) => x
- } else None
- }
-
- object AnnotationInfo extends AnnotationInfoExtractor
-
- lazy val classfileAnnotArgManifest: ClassManifest[ClassfileAnnotArg] =
- reflect.ClassManifest.classType(classOf[ClassfileAnnotArg])
-
- /** Symbol annotations parsed in Namer (typeCompleter of
- * definitions) have to be lazy (#1782)
- */
- case class LazyAnnotationInfo(annot: () => AnnotationInfo)
- extends AnnotationInfoBase
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
index c3dd5f4da3..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
+++ b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
@@ -1,251 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-package scala.tools.nsc
-package symtab
-
-// todo implement in terms of BitSet
-import scala.collection.mutable.{ListBuffer, BitSet}
-import math.max
-import util.Statistics._
-
-/** A base type sequence (BaseTypeSeq) is an ordered sequence spanning all the base types
- * of a type. It characterized by the following two laws:
- *
- * (1) Each element of `tp.baseTypeSeq' is a basetype of `tp'
- * (2) For each basetype `bt1' of `tp' there is an element `bt' in `tp.baseTypeSeq' such that
- *
- * bt.typeSymbol = bt1.typeSymbol
- * bt <: bt1
- *
- * (3) The type symbols of different elements are different.
- *
- * Elements in the sequence are ordered by Symbol.isLess.
- * @note base type sequences were called closures up to 2.7.1. The name has been changed
- * to avoid confusion with function closures.
- */
-trait BaseTypeSeqs {
- this: SymbolTable =>
- import definitions._
-
- class BaseTypeSeq(parents: List[Type], elems: Array[Type]) {
- self =>
- incCounter(baseTypeSeqCount)
- incCounter(baseTypeSeqLenTotal, elems.length)
-
- /** The number of types in the sequence */
- def length: Int = elems.length
-
- // #3676 shows why we can't store NoType in elems to mark cycles
- // (while NoType is in there to indicate a cycle in this BTS, during the execution of
- // the mergePrefixAndArgs below, the elems get copied without the pending map,
- // so that NoType's are seen instead of the original type --> spurious compile error)
- val pending = new BitSet(length)
-
- /** The type at i'th position in this sequence; lazy types are returned evaluated. */
- def apply(i: Int): Type =
- if(pending contains i) {
- pending.clear()
- throw CyclicInheritance
- } else
- elems(i) match {
- case rtp @ RefinedType(variants, decls) =>
- // can't assert decls.isEmpty; see t0764
- //if (!decls.isEmpty) assert(false, "computing closure of "+this+":"+this.isInstanceOf[RefinedType]+"/"+closureCache(j))
- //Console.println("compute closure of "+this+" => glb("+variants+")")
- pending += i
- try {
- mergePrefixAndArgs(variants, -1, lubDepth(variants)) match {
- case Some(tp0) =>
- pending(i) = false
- elems(i) = tp0
- tp0
- case None =>
- typeError(
- "no common type instance of base types "+(variants mkString ", and ")+" exists.")
- }
- } catch {
- case CyclicInheritance =>
- typeError(
- "computing the common type instance of base types "+(variants mkString ", and ")+" leads to a cycle.")
- }
- case tp =>
- tp
- }
-
- def rawElem(i: Int) = elems(i)
-
- /** The type symbol of the type at i'th position in this sequence;
- * no evaluation needed.
- */
- def typeSymbol(i: Int): Symbol = {
- elems(i) match {
- case RefinedType(v :: vs, _) => v.typeSymbol
- case tp => tp.typeSymbol
- }
- }
-
- /** Return all evaluated types in this sequence as a list */
- def toList: List[Type] = elems.toList
-
- protected def copy(head: Type, offset: Int): BaseTypeSeq = {
- val arr = new Array[Type](elems.length + offset)
- compat.Platform.arraycopy(elems, 0, arr, offset, elems.length)
- arr(0) = head
- new BaseTypeSeq(parents, arr)
- }
-
- /** Compute new base type sequence with `tp' prepended to this sequence */
- def prepend(tp: Type): BaseTypeSeq = copy(tp, 1)
-
- /** Compute new base type sequence with `tp' replacing the head of this sequence */
- def updateHead(tp: Type): BaseTypeSeq = copy(tp, 0)
-
- /** Compute new base type sequence where every element is mapped
- * with function `f'. Lazy types are mapped but not evaluated */
- def map(f: Type => Type): BaseTypeSeq = {
- // inlined `elems map f' for performance
- val len = length
- var arr = new Array[Type](len)
- var i = 0
- while (i < len) {
- arr(i) = f(elems(i))
- i += 1
- }
- new BaseTypeSeq(parents, arr)
- }
-
- def lateMap(f: Type => Type): BaseTypeSeq = new BaseTypeSeq(parents map f, elems) {
- override def apply(i: Int) = f(self.apply(i))
- override def rawElem(i: Int) = f(self.rawElem(i))
- override def typeSymbol(i: Int) = self.typeSymbol(i)
- override def toList = self.toList map f
- override protected def copy(head: Type, offset: Int) = (self map f).copy(head, offset)
- override def map(g: Type => Type) = lateMap(g)
- override def lateMap(g: Type => Type) = self.lateMap(x => g(f(x)))
- override def exists(p: Type => Boolean) = elems exists (x => p(f(x)))
- override protected def maxDepthOfElems: Int = elems map (x => maxDpth(f(x))) max
- override def toString = elems.mkString("MBTS(", ",", ")")
- }
-
- def exists(p: Type => Boolean): Boolean = elems exists p
-
- lazy val maxDepth: Int = maxDepthOfElems
-
- protected def maxDepthOfElems = {
- var d = 0
- for (i <- 0 until length) d = max(d, maxDpth(elems(i)))
- d
- }
-
- /** The maximum depth of type `tp' */
- protected def maxDpth(tp: Type): Int = tp match {
- case TypeRef(pre, sym, args) =>
- max(maxDpth(pre), maxDpth(args) + 1)
- case RefinedType(parents, decls) =>
- max(maxDpth(parents), maxDpth(decls.toList.map(_.info)) + 1)
- case TypeBounds(lo, hi) =>
- max(maxDpth(lo), maxDpth(hi))
- case MethodType(paramtypes, result) =>
- maxDpth(result)
- case NullaryMethodType(result) =>
- maxDpth(result)
- case PolyType(tparams, result) =>
- max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
- case ExistentialType(tparams, result) =>
- max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
- case _ =>
- 1
- }
-
- /** The maximum depth of all types `tps' */
- private def maxDpth(tps: Seq[Type]): Int = {
- var d = 0
- for (tp <- tps) d = max(d, maxDpth(tp))
- d
- }
-
- override def toString = elems.mkString("BTS(", ",", ")")
-
- private def typeError(msg: String): Nothing =
- throw new TypeError(
- "the type intersection "+(parents mkString " with ")+" is malformed"+
- "\n --- because ---\n"+msg)
- }
-
- /** A merker object for a base type sequence that's no yet computed.
- * used to catch inheritance cycles
- */
- val undetBaseTypeSeq: BaseTypeSeq = new BaseTypeSeq(List(), Array())
-
- /** Create a base type sequence consisting of a single type */
- def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = new BaseTypeSeq(List(), Array(tp))
-
- /** Create the base type sequence of a compound type wuth given tp.parents */
- def compoundBaseTypeSeq(tp: Type): BaseTypeSeq = {
- val tsym = tp.typeSymbol
- val parents = tp.parents
-// Console.println("computing baseTypeSeq of " + tsym.tpe + " " + parents)//DEBUG
- val buf = new ListBuffer[Type]
- buf += tsym.tpe
- var btsSize = 1
- if (parents.nonEmpty) {
- val nparents = parents.length
- val pbtss = new Array[BaseTypeSeq](nparents)
- val index = new Array[Int](nparents)
- var i = 0
- for (p <- parents) {
- pbtss(i) =
- if (p.baseTypeSeq eq undetBaseTypeSeq) AnyClass.info.baseTypeSeq
- else p.baseTypeSeq
- index(i) = 0
- i += 1
- }
- def nextTypeSymbol(i: Int): Symbol = {
- val j = index(i)
- val pbts = pbtss(i)
- if (j < pbts.length) pbts.typeSymbol(j) else AnyClass
- }
- def nextRawElem(i: Int): Type = {
- val j = index(i)
- val pbts = pbtss(i)
- if (j < pbts.length) pbts.rawElem(j) else AnyClass.tpe
- }
- var minSym: Symbol = NoSymbol
- while (minSym != AnyClass) {
- minSym = nextTypeSymbol(0)
- i = 1
- while (i < nparents) {
- val nextSym = nextTypeSymbol(i)
- if (nextSym isLess minSym)
- minSym = nextSym
- i += 1
- }
- var minTypes: List[Type] = List()
- i = 0
- while (i < nparents) {
- if (nextTypeSymbol(i) == minSym) {
- nextRawElem(i) match {
- case RefinedType(variants, decls) =>
- for (tp <- variants)
- if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes
- case tp =>
- if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes
- }
- index(i) = index(i) + 1
- }
- i += 1
- }
- buf += intersectionType(minTypes)
- btsSize += 1
- }
- }
- val elems = new Array[Type](btsSize)
- buf.copyToArray(elems, 0)
-// Console.println("computed baseTypeSeq of " + tsym.tpe + " " + parents + ": "+elems.toString)//DEBUG
- new BaseTypeSeq(parents, elems)
- }
-
- val CyclicInheritance = new Throwable
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala
index b024d550b7..060b3c5ce4 100644
--- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala
@@ -6,7 +6,6 @@
package scala.tools.nsc
package symtab
-import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.util.BatchSourceFile
/** A subclass of SymbolLoaders that implements browsing behavior.
diff --git a/src/compiler/scala/tools/nsc/symtab/Caches.scala b/src/compiler/scala/tools/nsc/symtab/Caches.scala
index 10d7500f09..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Caches.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Caches.scala
@@ -1,103 +0,0 @@
-/* NSC -- new scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package symtab
-
-import scala.collection.{ mutable, immutable }
-
-/** A cache for some entity whose validity depends on a monotonically
- * increasing sequence number.
- */
-abstract class SequencedCache[T >: Null] {
- def zero: Int
- def sequenceId: Int
- def calculate(): T
-
- /** If sequence numbers differ, this condition is consulted before
- * updating the cached value.
- */
- def isCacheValid: Boolean
-
- /** Public so accesses can be inlined. */
- @inline var cachedId: Int = 0
- @inline var cachedValue: T = _
-
- /** Puts cache back in uninitialized state. */
- @inline final def clear() = {
- cachedId = zero
- cachedValue = null
- }
- /** Resets the sequence id without touching the cached value. */
- @inline final def reset() = {
- cachedId = zero
- }
-
- final def get(): T = {
- if (cachedValue == null) {
- cachedValue = calculate()
- cachedId = sequenceId
- }
- else if (cachedId != sequenceId) {
- if (!isCacheValid)
- cachedValue = calculate()
-
- cachedId = sequenceId
- }
- cachedValue
- }
-}
-
-trait Caches {
- self: SymbolTable =>
-
- final def isValid(period: Period): Boolean =
- period != 0 && runId(period) == currentRunId && {
- val pid = phaseId(period)
- if (phase.id > pid) infoTransformers.nextFrom(pid).pid >= phase.id
- else infoTransformers.nextFrom(phase.id).pid >= pid
- }
-
- final def isValidForBaseClasses(period: Period): Boolean = {
- def noChangeInBaseClasses(it: InfoTransformer, limit: Phase#Id): Boolean = (
- it.pid >= limit ||
- !it.changesBaseClasses && noChangeInBaseClasses(it.next, limit)
- );
- period != 0 && runId(period) == currentRunId && {
- val pid = phaseId(period)
- if (phase.id > pid) noChangeInBaseClasses(infoTransformers.nextFrom(pid), phase.id)
- else noChangeInBaseClasses(infoTransformers.nextFrom(phase.id), pid)
- }
- }
-
- abstract class PeriodCache[T >: Null] extends SequencedCache[T] {
- final val zero = NoPeriod
- @inline final def sequenceId = currentPeriod
- }
-
- abstract class ListOfTypesCache extends PeriodCache[List[Type]] {
- @inline final def isCacheValid = isValidForBaseClasses(cachedId)
- }
- abstract class ListOfSymbolsCache extends PeriodCache[List[Symbol]] {
- @inline final def isCacheValid = isValidForBaseClasses(cachedId)
- }
- abstract class BaseTypeSeqCache extends PeriodCache[BaseTypeSeq] {
- @inline final def isCacheValid = isValidForBaseClasses(cachedId)
- }
- abstract class TypeCache extends PeriodCache[Type] {
- @inline final def isCacheValid = isValid(cachedId)
- }
- abstract class TypeCacheForRunId extends SequencedCache[Type] {
- final val zero = NoRunId
- @inline final def sequenceId = currentRunId
- @inline final override def isCacheValid = false
- }
- object TypeCache {
- def apply(body: => Type): TypeCache = new TypeCache {
- @inline final def calculate() = body
- }
- }
-}
-
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index e74de01016..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -1,220 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-
-// Flags at each index of a flags Long. Those marked with /M are used in
-// Parsers/JavaParsers and therefore definitely appear on Modifiers; but the
-// absence of /M on the other flags does not imply they aren't.
-//
-// Generated by mkFlagsTable() at Mon Oct 11 10:01:09 PDT 2010
-//
-// 0: PROTECTED/M
-// 1: OVERRIDE/M
-// 2: PRIVATE/M
-// 3: ABSTRACT/M
-// 4: DEFERRED/M
-// 5: FINAL/M
-// 6: METHOD
-// 7: INTERFACE/M
-// 8: MODULE
-// 9: IMPLICIT/M
-// 10: SEALED/M
-// 11: CASE/M
-// 12: MUTABLE/M
-// 13: PARAM/M
-// 14: PACKAGE
-// 15:
-// 16: BYNAMEPARAM/M CAPTURED COVARIANT/M
-// 17: CONTRAVARIANT/M INCONSTRUCTOR LABEL
-// 18: ABSOVERRIDE/M
-// 19: LOCAL/M
-// 20: JAVA/M
-// 21: SYNTHETIC
-// 22: STABLE
-// 23: STATIC/M
-// 24: CASEACCESSOR/M
-// 25: DEFAULTPARAM/M TRAIT/M
-// 26: BRIDGE
-// 27: ACCESSOR
-// 28: SUPERACCESSOR
-// 29: PARAMACCESSOR/M
-// 30: MODULEVAR
-// 31: LAZY/M
-// 32: IS_ERROR
-// 33: OVERLOADED
-// 34: LIFTED
-// 35: EXISTENTIAL MIXEDIN
-// 36: EXPANDEDNAME
-// 37: IMPLCLASS PRESUPER/M
-// 38: TRANS_FLAG
-// 39: LOCKED
-// 40: SPECIALIZED
-// 41: DEFAULTINIT/M
-// 42: VBRIDGE
-// 43: VARARGS
-// 44:
-// 45:
-// 46:
-// 47:
-// 48:
-// 49: latePRIVATE
-// 50: lateABSTRACT
-// 51: lateDEFERRED
-// 52: lateFINAL
-// 53: lateMETHOD
-// 54: lateINTERFACE
-// 55: lateMODULE
-// 56: notPROTECTED
-// 57: notOVERRIDE
-// 58: notPRIVATE
-// 59: notABSTRACT
-// 60: notDEFERRED
-// 61: notFINAL
-// 62: notMETHOD
-// 63:
-class Flags extends reflect.generic.Flags {
-
- final val InitialFlags = 0x0001FFFFFFFFFFFFL // flags that are enabled from phase 1.
- final val LateFlags = 0x00FE000000000000L // flags that override flags in 0x1FC.
- final val AntiFlags = 0x7F00000000000000L // flags that cancel flags in 0x07F
- final val LateShift = 47L
- final val AntiShift = 56L
-
- // late flags (set by a transformer phase)
- final val latePRIVATE = (PRIVATE: Long) << LateShift
- final val lateABSTRACT = (ABSTRACT: Long) << LateShift
- final val lateDEFERRED = (DEFERRED: Long) << LateShift
- final val lateINTERFACE = (INTERFACE: Long) << LateShift
- final val lateMODULE = (MODULE: Long) << LateShift
- final val lateFINAL = (FINAL: Long) << LateShift
- final val lateMETHOD = (METHOD: Long) << LateShift
-
- final val notFINAL = (FINAL: Long) << AntiShift
- final val notPRIVATE = (PRIVATE: Long) << AntiShift
- final val notDEFERRED = (DEFERRED: Long) << AntiShift
- final val notPROTECTED = (PROTECTED: Long) << AntiShift
- final val notABSTRACT = (ABSTRACT: Long) << AntiShift
- final val notOVERRIDE = (OVERRIDE: Long) << AntiShift
- final val notMETHOD = (METHOD: Long) << AntiShift
-
- final val notFlagMap = Map[Int, Long](
- FINAL -> notFINAL,
- PRIVATE -> notPRIVATE,
- DEFERRED -> notDEFERRED,
- PROTECTED -> notPROTECTED,
- ABSTRACT -> notABSTRACT,
- OVERRIDE -> notOVERRIDE,
- METHOD -> notMETHOD
- )
-
- // masks
- /** These flags can be set when class or module symbol is first created. */
- final val TopLevelCreationFlags: Long =
- MODULE | PACKAGE | FINAL | JAVA
-
- /** These modifiers can be set explicitly in source programs. */
- final val ExplicitFlags: Long =
- PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED |
- OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE | LAZY
-
- /** These modifiers appear in TreePrinter output. */
- final val PrintableFlags: Long =
- ExplicitFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR |
- ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | BRIDGE | STATIC | VBRIDGE | SPECIALIZED
-
- /** The two bridge flags */
- final val BRIDGES = BRIDGE | VBRIDGE
-
- final val FieldFlags: Long =
- MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL | PRESUPER | LAZY
-
- final val AccessFlags: Long = PRIVATE | PROTECTED | LOCAL
- final val VarianceFlags = COVARIANT | CONTRAVARIANT
- final val ConstrFlags: Long = JAVA
-
- /** Module flags inherited by their module-class */
- final val ModuleToClassFlags: Long = AccessFlags | MODULE | PACKAGE | CASE | SYNTHETIC | JAVA
-
- def getterFlags(fieldFlags: Long): Long = ACCESSOR + (
- if ((fieldFlags & MUTABLE) != 0) fieldFlags & ~MUTABLE & ~PRESUPER
- else fieldFlags & ~PRESUPER | STABLE
- )
-
- def setterFlags(fieldFlags: Long): Long =
- getterFlags(fieldFlags) & ~STABLE & ~CASEACCESSOR
-
- // Generated by mkFlagToStringMethod() at Mon Oct 11 10:12:36 PDT 2010
- @annotation.switch override def flagToString(flag: Long): String = flag match {
- case PROTECTED => "protected" // (1L << 0)
- case OVERRIDE => "override" // (1L << 1)
- case PRIVATE => "private" // (1L << 2)
- case ABSTRACT => "abstract" // (1L << 3)
- case DEFERRED => "<deferred>" // (1L << 4)
- case FINAL => "final" // (1L << 5)
- case METHOD => "<method>" // (1L << 6)
- case INTERFACE => "<interface>" // (1L << 7)
- case MODULE => "<module>" // (1L << 8)
- case IMPLICIT => "implicit" // (1L << 9)
- case SEALED => "sealed" // (1L << 10)
- case CASE => "case" // (1L << 11)
- case MUTABLE => "<mutable>" // (1L << 12)
- case PARAM => "<param>" // (1L << 13)
- case PACKAGE => "<package>" // (1L << 14)
- case 0x8000L => "" // (1L << 15)
- case BYNAMEPARAM => "<bynameparam/captured/covariant>" // (1L << 16)
- case CONTRAVARIANT => "<contravariant/inconstructor/label>" // (1L << 17)
- case ABSOVERRIDE => "absoverride" // (1L << 18)
- case LOCAL => "<local>" // (1L << 19)
- case JAVA => "<java>" // (1L << 20)
- case SYNTHETIC => "<synthetic>" // (1L << 21)
- case STABLE => "<stable>" // (1L << 22)
- case STATIC => "<static>" // (1L << 23)
- case CASEACCESSOR => "<caseaccessor>" // (1L << 24)
- case DEFAULTPARAM => "<defaultparam/trait>" // (1L << 25)
- case BRIDGE => "<bridge>" // (1L << 26)
- case ACCESSOR => "<accessor>" // (1L << 27)
- case SUPERACCESSOR => "<superaccessor>" // (1L << 28)
- case PARAMACCESSOR => "<paramaccessor>" // (1L << 29)
- case MODULEVAR => "<modulevar>" // (1L << 30)
- case LAZY => "lazy" // (1L << 31)
- case IS_ERROR => "<is_error>" // (1L << 32)
- case OVERLOADED => "<overloaded>" // (1L << 33)
- case LIFTED => "<lifted>" // (1L << 34)
- case EXISTENTIAL => "<existential/mixedin>" // (1L << 35)
- case EXPANDEDNAME => "<expandedname>" // (1L << 36)
- case IMPLCLASS => "<implclass/presuper>" // (1L << 37)
- case TRANS_FLAG => "<trans_flag>" // (1L << 38)
- case LOCKED => "<locked>" // (1L << 39)
- case SPECIALIZED => "<specialized>" // (1L << 40)
- case DEFAULTINIT => "<defaultinit>" // (1L << 41)
- case VBRIDGE => "<vbridge>" // (1L << 42)
- case VARARGS => "<varargs>" // (1L << 43)
- case 0x100000000000L => "" // (1L << 44)
- case 0x200000000000L => "" // (1L << 45)
- case 0x400000000000L => "" // (1L << 46)
- case 0x800000000000L => "" // (1L << 47)
- case 0x1000000000000L => "" // (1L << 48)
- case `latePRIVATE` => "<lateprivate>" // (1L << 49)
- case `lateABSTRACT` => "<lateabstract>" // (1L << 50)
- case `lateDEFERRED` => "<latedeferred>" // (1L << 51)
- case `lateFINAL` => "<latefinal>" // (1L << 52)
- case `lateMETHOD` => "<latemethod>" // (1L << 53)
- case `lateINTERFACE` => "<lateinterface>" // (1L << 54)
- case `lateMODULE` => "<latemodule>" // (1L << 55)
- case `notPROTECTED` => "<notprotected>" // (1L << 56)
- case `notOVERRIDE` => "<notoverride>" // (1L << 57)
- case `notPRIVATE` => "<notprivate>" // (1L << 58)
- case `notABSTRACT` => "<notabstract>" // (1L << 59)
- case `notDEFERRED` => "<notdeferred>" // (1L << 60)
- case `notFINAL` => "<notfinal>" // (1L << 61)
- case `notMETHOD` => "<notmethod>" // (1L << 62)
- case 0x8000000000000000L => "" // (1L << 63)
- case _ => ""
- }
-}
-
-object Flags extends Flags { }
diff --git a/src/compiler/scala/tools/nsc/symtab/InfoTransformers.scala b/src/compiler/scala/tools/nsc/symtab/InfoTransformers.scala
index 69896c634f..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/InfoTransformers.scala
+++ b/src/compiler/scala/tools/nsc/symtab/InfoTransformers.scala
@@ -1,47 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-
-trait InfoTransformers {
- self: SymbolTable =>
-
- abstract class InfoTransformer {
- var prev: InfoTransformer = this
- var next: InfoTransformer = this
-
- val pid: Phase#Id
- val changesBaseClasses: Boolean
- def transform(sym: Symbol, tpe: Type): Type
-
- def insert(that: InfoTransformer) {
- assert(this.pid != that.pid)
- if (that.pid < this.pid) {
- prev insert that
- } else if (next.pid <= that.pid && next.pid != NoPhase.id) {
- next insert that
- } else {
- that.next = next
- that.prev = this
- next.prev = that
- this.next = that
- }
- }
-
- /** The InfoTransformer whose (pid == from).
- * If no such exists, the InfoTransformer with the next
- * higher pid.
- */
- def nextFrom(from: Phase#Id): InfoTransformer =
- if (from == this.pid) this
- else if (from < this.pid)
- if (prev.pid < from) this
- else prev.nextFrom(from);
- else if (next.pid == NoPhase.id) next
- else next.nextFrom(from)
- }
-}
-
diff --git a/src/compiler/scala/tools/nsc/symtab/NameManglers.scala b/src/compiler/scala/tools/nsc/symtab/NameManglers.scala
index 5ef0da8282..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/NameManglers.scala
+++ b/src/compiler/scala/tools/nsc/symtab/NameManglers.scala
@@ -1,172 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-
-import java.security.MessageDigest
-import scala.io.Codec
-import util.Chars.isOperatorPart
-
-/** A trait to encapsulate name mangling. It's intended for the
- * values and methods involved in assembling names out of other names,
- * and not for simple synthetically named locals.
- */
-trait NameManglers {
- self: SymbolTable =>
-
- trait NameManglingCommon {
- self: CompilerCommonNames =>
-
- def flattenedName(segments: Name*): NameType = compactedString(segments mkString "$")
-
- /**
- * COMPACTIFY
- *
- * The hashed name has the form (prefix + marker + md5 + marker + suffix), where
- * - prefix/suffix.length = MaxNameLength / 4
- * - md5.length = 32
- *
- * We obtain the formula:
- *
- * FileNameLength = 2*(MaxNameLength / 4) + 2.marker.length + 32 + 6
- *
- * (+6 for ".class"). MaxNameLength can therefore be computed as follows:
- */
- private final val marker = "$$$$"
- private final val MaxNameLength = math.min(
- settings.maxClassfileName.value - 6,
- 2 * (settings.maxClassfileName.value - 6 - 2*marker.length - 32)
- )
- private lazy val md5 = MessageDigest.getInstance("MD5")
- private def toMD5(s: String, edge: Int) = {
- val prefix = s take edge
- val suffix = s takeRight edge
-
- val cs = s.toArray
- val bytes = Codec toUTF8 cs
- md5 update bytes
- val md5chars = md5.digest() map (b => (b & 0xFF).toHexString) mkString
-
- prefix + marker + md5chars + marker + suffix
- }
- private def compactedString(s: String) =
- if (s.length <= MaxNameLength) s
- else toMD5(s, MaxNameLength / 4)
- }
-
- trait TypeNameMangling extends NameManglingCommon {
- self: tpnme.type =>
-
- }
-
- trait TermNameMangling extends NameManglingCommon {
- self: nme.type =>
-
- val IMPL_CLASS_SUFFIX = "$class"
- val SINGLETON_SUFFIX = ".type"
- val LOCALDUMMY_PREFIX = "<local " // owner of local blocks
- val PROTECTED_PREFIX = "protected$"
- val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set"
- val SELECTOR_DUMMY = "<unapply-selector>"
- val SETTER_SUFFIX = encode("_=")
- val SUPER_PREFIX_STRING = "super$"
- val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$"
-
- def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR
- def isExceptionResultName(name: Name) = name startsWith EXCEPTION_RESULT_PREFIX
- /** !!! Foo$class$1 is an implClassName, I think. */
- def isImplClassName(name: Name) = name endsWith IMPL_CLASS_SUFFIX
- def isLocalDummyName(name: Name) = name startsWith LOCALDUMMY_PREFIX
- def isLocalName(name: Name) = name endsWith LOCAL_SUFFIX_STRING
- def isLoopHeaderLabel(name: Name) = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX)
- def isProtectedAccessorName(name: Name) = name startsWith PROTECTED_PREFIX
- def isReplWrapperName(name: Name) = name containsName INTERPRETER_IMPORT_WRAPPER
- def isSetterName(name: Name) = name endsWith SETTER_SUFFIX
- def isTraitSetterName(name: Name) = isSetterName(name) && (name containsName TRAIT_SETTER_SEPARATOR_STRING)
- def isSingletonName(name: Name) = name endsWith SINGLETON_SUFFIX
-
- def isOpAssignmentName(name: Name) = name match {
- case raw.NE | raw.LE | raw.GE | EMPTY => false
- case _ =>
- name.endChar == '=' && name.startChar != '=' && isOperatorPart(name.startChar)
- }
-
- /** The expanded setter name of `name' relative to this class `base`
- */
- def expandedSetterName(name: TermName, base: Symbol): TermName =
- expandedName(name, base, separator = TRAIT_SETTER_SEPARATOR_STRING)
-
- /** If `name' is an expandedName name, the original name.
- * Otherwise `name' itself.
- */
- def originalName(name: Name): Name = {
- var i = name.length
- while (i >= 2 && !(name(i - 1) == '$' && name(i - 2) == '$')) i -= 1
- if (i >= 2) {
- while (i >= 3 && name(i - 3) == '$') i -= 1
- name.subName(i, name.length)
- } else name
- }
-
- /** Return the original name and the types on which this name
- * is specialized. For example,
- * {{{
- * splitSpecializedName("foo$mIcD$sp") == ('foo', "I", "D")
- * }}}
- * `foo$mIcD$sp` is the name of a method specialized on two type
- * parameters, the first one belonging to the method itself, on Int,
- * and another one belonging to the enclosing class, on Double.
- */
- def splitSpecializedName(name: Name): (Name, String, String) =
- if (name.endsWith("$sp")) {
- val name1 = name stripEnd "$sp"
- val idxC = name1 lastIndexOf 'c'
- val idxM = name1 lastIndexOf 'm'
-
- (name1.subName(0, idxM - 1),
- name1.subName(idxC + 1, name1.length).toString,
- name1.subName(idxM + 1, idxC).toString)
- } else
- (name, "", "")
-
- def getterName(name: TermName): TermName = if (isLocalName(name)) localToGetter(name) else name
- def getterToLocal(name: TermName): TermName = name.toTermName append LOCAL_SUFFIX_STRING
- def getterToSetter(name: TermName): TermName = name.toTermName append SETTER_SUFFIX
- def localToGetter(name: TermName): TermName = name stripEnd LOCAL_SUFFIX_STRING toTermName
-
- def setterToGetter(name: TermName): TermName = {
- val p = name.pos(TRAIT_SETTER_SEPARATOR_STRING)
- if (p < name.length)
- setterToGetter(name.subName(p + TRAIT_SETTER_SEPARATOR_STRING.length, name.length))
- else
- name stripEnd SETTER_SUFFIX toTermName
- }
-
- def defaultGetterName(name: Name, pos: Int): TermName = {
- val prefix = if (isConstructorName(name)) "init" else name
- newTermName(prefix + DEFAULT_GETTER_STRING + pos)
- }
- def defaultGetterToMethod(name: Name): TermName = {
- val p = name.pos(DEFAULT_GETTER_STRING)
- if (p < name.length) name.subName(0, p)
- else name
- }
-
- def dropSingletonName(name: Name): TypeName = name stripEnd SINGLETON_SUFFIX toTypeName
- def singletonName(name: Name): TypeName = name append SINGLETON_SUFFIX toTypeName
- def implClassName(name: Name): TypeName = name append IMPL_CLASS_SUFFIX toTypeName
- def interfaceName(implname: Name): TypeName = implname stripEnd IMPL_CLASS_SUFFIX toTypeName
- def localDummyName(clazz: Symbol): TermName = newTermName(LOCALDUMMY_PREFIX + clazz.name + ">")
- def productAccessorName(i: Int): TermName = newTermName("_" + i)
- def superName(name: Name): TermName = newTermName(SUPER_PREFIX_STRING + name)
-
- /** The name of an accessor for protected symbols. */
- def protName(name: Name): TermName = newTermName(PROTECTED_PREFIX + name)
-
- /** The name of a setter for protected symbols. Used for inherited Java fields. */
- def protSetterName(name: Name): TermName = newTermName(PROTECTED_SET_PREFIX + name)
- }
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/Names.scala b/src/compiler/scala/tools/nsc/symtab/Names.scala
index 7eccb9a49f..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Names.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Names.scala
@@ -1,429 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-
-import scala.reflect.NameTransformer
-import scala.io.Codec
-import java.security.MessageDigest
-
-/** The class Names ...
- *
- * @author Martin Odersky
- * @version 1.0, 05/02/2005
- */
-trait Names extends reflect.generic.Names {
-
-// Operations -------------------------------------------------------------
-
- private final val HASH_SIZE = 0x8000
- private final val HASH_MASK = 0x7FFF
- private final val NAME_SIZE = 0x20000
-
- final val nameDebug = false
-
- /** memory to store all names sequentially
- */
- var chrs: Array[Char] = new Array[Char](NAME_SIZE)
- private var nc = 0
-
- /** hashtable for finding term names quickly
- */
- private val termHashtable = new Array[TermName](HASH_SIZE)
-
- /** hashtable for finding type names quickly
- */
- private val typeHashtable = new Array[TypeName](HASH_SIZE)
-
- /** the hashcode of a name
- */
- private def hashValue(cs: Array[Char], offset: Int, len: Int): Int =
- if (len > 0)
- (len * (41 * 41 * 41) +
- cs(offset) * (41 * 41) +
- cs(offset + len - 1) * 41 +
- cs(offset + (len >> 1)))
- else 0;
-
- /** Is (the ASCII representation of) name at given index equal to
- * cs[offset..offset+len-1]?
- */
- private def equals(index: Int, cs: Array[Char], offset: Int, len: Int): Boolean = {
- var i = 0
- while ((i < len) && (chrs(index + i) == cs(offset + i)))
- i += 1;
- i == len
- }
-
- /** enter characters into chrs array
- */
- private def enterChars(cs: Array[Char], offset: Int, len: Int) {
- var i = 0
- while (i < len) {
- if (nc + i == chrs.length) {
- val newchrs = new Array[Char](chrs.length * 2)
- compat.Platform.arraycopy(chrs, 0, newchrs, 0, chrs.length)
- chrs = newchrs
- }
- chrs(nc + i) = cs(offset + i)
- i += 1
- }
- if (len == 0) nc += 1
- else nc = nc + len
- }
-
- /** Create a term name from the characters in cs[offset..offset+len-1].
- */
- def newTermName(cs: Array[Char], offset: Int, len: Int): TermName = {
- val h = hashValue(cs, offset, len) & HASH_MASK
- var n = termHashtable(h)
- while ((n ne null) && (n.length != len || !equals(n.start, cs, offset, len)))
- n = n.next;
- if (n eq null) {
- n = new TermName(nc, len, h)
- enterChars(cs, offset, len)
- }
- n
- }
-
- /** create a term name from string
- */
- def newTermName(s: String): TermName =
- newTermName(s.toCharArray(), 0, s.length())
-
- /** Create a term name from the UTF8 encoded bytes in bs[offset..offset+len-1].
- */
- def newTermName(bs: Array[Byte], offset: Int, len: Int): TermName =
- newTermName(Codec fromUTF8 bs.slice(offset, offset + len) mkString)
-
- /** Create a type name from the characters in cs[offset..offset+len-1].
- */
- def newTypeName(cs: Array[Char], offset: Int, len: Int): TypeName =
- newTermName(cs, offset, len).toTypeName
-
- /** Create a type name from string
- */
- def newTypeName(s: String): TypeName =
- newTermName(s).toTypeName
-
- /** Create a type name from the UTF8 encoded bytes in bs[offset..offset+len-1].
- */
- def newTypeName(bs: Array[Byte], offset: Int, len: Int): TypeName =
- newTermName(bs, offset, len).toTypeName
-
- def mkTermName(name: Name): TermName = name.toTermName
- def mkTypeName(name: Name): TypeName = name.toTypeName
- def isTermName(name: Name): Boolean = name.isTermName
- def isTypeName(name: Name): Boolean = name.isTypeName
-
- def nameChars: Array[Char] = chrs
- @deprecated("", "2.9.0") def view(s: String): TermName = newTermName(s)
-
-// Classes ----------------------------------------------------------------------
-
- /** The name class. */
- sealed abstract class Name(protected val index: Int, protected val len: Int) extends Function1[Int, Char] {
- /** Index into name table */
- def start: Int = index
-
- /** next name in the same hash bucket
- */
- def next: Name
-
- /** return the length of this name
- */
- final def length: Int = len
- final def isEmpty = length == 0
- final def nonEmpty = !isEmpty
-
- def isTermName: Boolean
- def isTypeName: Boolean
- def toTermName: TermName
- def toTypeName: TypeName
- def companionName: Name
- def bothNames: List[Name] = List(toTermName, toTypeName)
-
- /** Copy bytes of this name to buffer cs, starting at position `offset`.
- */
- final def copyChars(cs: Array[Char], offset: Int) =
- compat.Platform.arraycopy(chrs, index, cs, offset, len)
-
- /** return the ascii representation of this name
- */
- final def toChars: Array[Char] = {
- val cs = new Array[Char](len)
- copyChars(cs, 0)
- cs
- }
-
- /** return the string representation of this name
- */
- final override def toString(): String = new String(chrs, index, len)
- def debugString() = NameTransformer.decode(toString) + (if (isTypeName) "!" else "")
-
- /** Write to UTF8 representation of this name to given character array.
- * Start copying to index `to'. Return index of next free byte in array.
- * Array must have enough remaining space for all bytes
- * (i.e. maximally 3*length bytes).
- */
- final def copyUTF8(bs: Array[Byte], offset: Int): Int = {
- val bytes = Codec toUTF8 chrs.slice(index, index + len)
- compat.Platform.arraycopy(bytes, 0, bs, offset, bytes.length)
- offset + bytes.length
- }
-
- /** return the hash value of this name
- */
- final override def hashCode(): Int = index
-
- // Presently disabled.
- // override def equals(other: Any) = paranoidEquals(other)
- private def paranoidEquals(other: Any): Boolean = {
- val cmp = this eq other.asInstanceOf[AnyRef]
- if (cmp || !nameDebug)
- return cmp
-
- other match {
- case x: String =>
- Console.println("Compared " + debugString + " and String '" + x + "'")
- case x: Name =>
- if (this.isTermName != x.isTermName) {
- val panic = this.toTermName == x.toTermName
- Console.println("Compared '%s' and '%s', one term, one type.%s".format(this, x,
- if (panic) " And they contain the same name string!"
- else ""
- ))
- }
- case _ =>
- }
- false
- }
-
- /** return the i'th Char of this name
- */
- final def apply(i: Int): Char = chrs(index + i)
-
- /** return the index of first occurrence of char c in this name, length if not found */
- final def pos(c: Char): Int = pos(c, 0)
-
- /** return the index of first occurrence of char c in this name, length if not found */
- final def pos(s: String): Int = pos(s, 0)
-
- /** return the index of the first occurrence of character c in
- * this name from start, length if not found.
- *
- * @param c the character
- * @param start ...
- * @return the index of the first occurrence of c
- */
- final def pos(c: Char, start: Int): Int = {
- var i = start
- while (i < len && chrs(index + i) != c) i += 1
- i
- }
-
- /** return the index of the first occurrence of nonempty string s
- * in this name from start, length if not found.
- *
- * @param s the string
- * @param start ...
- * @return the index of the first occurrence of s
- */
- final def pos(s: String, start: Int): Int = {
- var i = pos(s.charAt(0), start)
- while (i + s.length() <= len) {
- var j = 1
- while (s.charAt(j) == chrs(index + i + j)) {
- j += 1
- if (j == s.length()) return i
- }
- i = pos(s.charAt(0), i + 1)
- }
- len
- }
-
- /** return the index of last occurrence of char c in this
- * name, -1 if not found.
- *
- * @param c the character
- * @return the index of the last occurrence of c
- */
- final def lastPos(c: Char): Int = lastPos(c, len - 1)
-
- final def lastPos(s: String): Int = lastPos(s, len - s.length)
-
- /** return the index of the last occurrence of char c in this
- * name from start, -1 if not found.
- *
- * @param c the character
- * @param start ...
- * @return the index of the last occurrence of c
- */
- final def lastPos(c: Char, start: Int): Int = {
- var i = start
- while (i >= 0 && chrs(index + i) != c) i -= 1
- i
- }
-
- /** return the index of the last occurrence of string s in this
- * name from start, -1 if not found.
- *
- * @param s the string
- * @param start ...
- * @return the index of the last occurrence of s
- */
- final def lastPos(s: String, start: Int): Int = {
- var i = lastPos(s.charAt(0), start)
- while (i >= 0) {
- var j = 1;
- while (s.charAt(j) == chrs(index + i + j)) {
- j += 1
- if (j == s.length()) return i;
- }
- i = lastPos(s.charAt(0), i - 1)
- }
- -s.length()
- }
-
- /** does this name start with prefix?
- */
- final def startsWith(prefix: Name): Boolean = startsWith(prefix, 0)
-
- /** does this name start with prefix at given start index?
- */
- final def startsWith(prefix: Name, start: Int): Boolean = {
- var i = 0
- while (i < prefix.length && start + i < len &&
- chrs(index + start + i) == chrs(prefix.start + i))
- i += 1;
- i == prefix.length
- }
-
- /** does this name end with suffix?
- */
- final def endsWith(suffix: Name): Boolean = endsWith(suffix, len)
-
- /** does this name end with suffix just before given end index?
- */
- final def endsWith(suffix: Name, end: Int): Boolean = {
- var i = 1
- while (i <= suffix.length && i <= end &&
- chrs(index + end - i) == chrs(suffix.start + suffix.length - i))
- i += 1;
- i > suffix.length
- }
-
- final def containsName(subname: String): Boolean = containsName(newTermName(subname))
- final def containsName(subname: Name): Boolean = {
- var start = 0
- val last = len - subname.length
- while (start <= last && !startsWith(subname, start)) start += 1
- start <= last
- }
-
- /** Some thoroughly self-explanatory convenience functions. They
- * assume that what they're being asked to do is known to be valid.
- */
- final def startChar: Char = apply(0)
- final def endChar: Char = apply(len - 1)
- final def startsWith(char: Char): Boolean = len > 0 && startChar == char
- final def startsWith(name: String): Boolean = startsWith(newTermName(name))
- final def endsWith(char: Char): Boolean = len > 0 && endChar == char
- final def endsWith(name: String): Boolean = endsWith(newTermName(name))
- final def stripStart(prefix: Name): Name = subName(prefix.length, len)
- final def stripStart(prefix: String): Name = subName(prefix.length, len)
- final def stripEnd(suffix: Name): Name = subName(0, len - suffix.length)
- final def stripEnd(suffix: String): Name = subName(0, len - suffix.length)
-
- def lastIndexOf(ch: Char) = toChars lastIndexOf ch
-
- /** Return the subname with characters from start to end-1.
- */
- def subName(from: Int, to: Int): Name
-
- /** Replace all occurrences of `from` by `to` in
- * name; result is always a term name.
- */
- def replace(from: Char, to: Char): Name = {
- val cs = new Array[Char](len)
- var i = 0
- while (i < len) {
- val ch = this(i)
- cs(i) = if (ch == from) to else ch
- i += 1
- }
- newTermName(cs, 0, len)
- }
-
- /** Replace operator symbols by corresponding $op_name.
- */
- def encode: Name = {
- val str = toString()
- val res = NameTransformer.encode(str)
- if (res == str) this
- else if (isTypeName) newTypeName(res)
- else newTermName(res)
- }
-
- def append(suffix: String): Name
- def append(suffix: Name): Name
-
- /** Replace $op_name by corresponding operator symbol.
- */
- def decode: String = (
- NameTransformer.decode(toString()) +
- (if (nameDebug && isTypeName) "!" else ""))//debug
-
- def isOperatorName: Boolean = decode != toString
- def nameKind: String = if (isTypeName) "type" else "term"
- def longString: String = nameKind + " " + NameTransformer.decode(toString)
- }
-
- final class TermName(_index: Int, _len: Int, hash: Int) extends Name(_index, _len) {
- var next: TermName = termHashtable(hash)
- termHashtable(hash) = this
- def isTermName: Boolean = true
- def isTypeName: Boolean = false
- def toTermName: TermName = this
- def toTypeName: TypeName = {
- val h = hashValue(chrs, index, len) & HASH_MASK
- var n = typeHashtable(h)
- while ((n ne null) && n.start != index)
- n = n.next;
- if (n eq null)
- n = new TypeName(index, len, h);
- n
- }
- def append(suffix: String): TermName = newTermName(this + suffix)
- def append(suffix: Name): TermName = append(suffix.toString)
- def companionName: TypeName = toTypeName
- def subName(from: Int, to: Int): TermName =
- newTermName(chrs, start + from, to - from)
- }
-
- final class TypeName(_index: Int, _len: Int, hash: Int) extends Name(_index, _len) {
- var next: TypeName = typeHashtable(hash)
- typeHashtable(hash) = this
- def isTermName: Boolean = false
- def isTypeName: Boolean = true
- def toTermName: TermName = {
- val h = hashValue(chrs, index, len) & HASH_MASK
- var n = termHashtable(h)
- while ((n ne null) && n.start != index)
- n = n.next;
- if (n eq null)
- n = new TermName(index, len, h);
- n
- }
- def toTypeName: TypeName = this
-
- def append(suffix: String): TypeName = newTypeName(this + suffix)
- def append(suffix: Name): TypeName = append(suffix.toString)
- def companionName: TermName = toTermName
- def subName(from: Int, to: Int): TypeName =
- newTypeName(chrs, start + from, to - from)
- }
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/Positions.scala b/src/compiler/scala/tools/nsc/symtab/Positions.scala
index 2290705bbf..ff20e70541 100644
--- a/src/compiler/scala/tools/nsc/symtab/Positions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Positions.scala
@@ -3,35 +3,19 @@ package symtab
import scala.tools.nsc.util.{ SourceFile, Position, OffsetPosition, NoPosition }
-trait Positions {
+trait Positions extends scala.reflect.common.Positions {
self: scala.tools.nsc.symtab.SymbolTable =>
def rangePos(source: SourceFile, start: Int, point: Int, end: Int) =
new OffsetPosition(source, point)
- /** A position that wraps a set of trees.
- * The point of the wrapping position is the point of the default position.
- * If some of the trees are ranges, returns a range position enclosing all ranges
- * Otherwise returns default position.
- */
- def wrappingPos(default: Position, trees: List[Tree]): Position = default
-
- /** A position that wraps the non-empty set of trees.
- * The point of the wrapping position is the point of the first trees' position.
- * If all some the trees are non-synthetic, returns a range position enclosing the non-synthetic trees
- * Otherwise returns a synthetic offset position to point.
- */
- def wrappingPos(trees: List[Tree]): Position = trees.head.pos
-
- /** Ensure that given tree has no positions that overlap with
- * any of the positions of `others`. This is done by
- * shortening the range or assigning TransparentPositions
- * to some of the nodes in `tree`.
- */
- def ensureNonOverlapping(tree: Tree, others: List[Tree]) {}
-
def validatePositions(tree: Tree) {}
type Position = scala.tools.nsc.util.Position
val NoPosition = scala.tools.nsc.util.NoPosition
+
+ def focusPos(pos: Position): Position = pos.focus
+ def isRangePos(pos: Position): Boolean = pos.isRange
+ def showPos(pos: Position): String = pos.show
+
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Scopes.scala b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
index dd79605cbe..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Scopes.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
@@ -1,336 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-
-// Martin: I am about 1/4 way on a cleanup of scopes.
-// The most important change is that scopes are now Iterables.
-// This removed the need for the various iterators on ScopeEntries.
-// ScopeEntries are conceptually an internal representation detail,
-// so it's better not to return them in public iterators.
-// It's true that other code also references ScopeEntries but that's
-// done for performance (and could be reviewed).
-// Another addition is a lookupAll method that returns all symbols with
-// a name in a scopein an iterator.
-trait Scopes {
- self: SymbolTable =>
-
- class ScopeEntry(val sym: Symbol, val owner: Scope) {
- /** the next entry in the hash bucket
- */
- var tail: ScopeEntry = null
-
- /** the next entry in this scope
- */
- var next: ScopeEntry = null
-
- override def hashCode(): Int = sym.name.start
- override def toString(): String = sym.toString()
- }
-
- /**
- * @param sym ...
- * @param owner ...
- * @return ...
- */
- private def newScopeEntry(sym: Symbol, owner: Scope): ScopeEntry = {
- val e = new ScopeEntry(sym, owner)
- e.next = owner.elems
- owner.elems = e
- e
- }
-
- class Scope(initElems: ScopeEntry) extends AbsScope {
-
- var elems: ScopeEntry = initElems
-
- /** The number of times this scope is nested in another
- */
- private var nestinglevel = 0
-
- /** the hash table
- */
- private var hashtable: Array[ScopeEntry] = null
-
- /** a cache for all elements, to be used by symbol iterator.
- */
- private var elemsCache: List[Symbol] = null
-
- /** size and mask of hash tables
- * todo: make hashtables grow?
- */
- private val HASHSIZE = 0x80
- private val HASHMASK = 0x7f
-
- /** the threshold number of entries from which a hashtable is constructed.
- */
- private val MIN_HASH = 8
-
- if (size >= MIN_HASH) createHash()
-
- def this() = this(null: ScopeEntry)
-
- def this(base: Scope) = {
- this(base.elems)
- nestinglevel = base.nestinglevel + 1
- }
-
- def this(decls: List[Symbol]) = {
- this()
- decls foreach enter
- }
-
- /** Returns a new scope with the same content as this one. */
- def cloneScope: Scope = {
- val clone = new Scope()
- this.toList foreach (clone enter _)
- clone
- }
-
- /** is the scope empty? */
- override def isEmpty: Boolean = elems eq null
-
- /** the number of entries in this scope */
- override def size: Int = {
- var s = 0
- var e = elems
- while (e ne null) {
- s += 1
- e = e.next
- }
- s
- }
-
- /** enter a scope entry
- *
- * @param e ...
- */
- def enter(e: ScopeEntry) {
- elemsCache = null
- if (hashtable ne null) {
- val i = e.sym.name.start & HASHMASK
- elems.tail = hashtable(i)
- hashtable(i) = elems
- } else if (size >= MIN_HASH) {
- createHash()
- }
- }
-
- /** enter a symbol
- *
- * @param sym ...
- */
- def enter(sym: Symbol): Symbol = { enter(newScopeEntry(sym, this)); sym }
-
- /** enter a symbol, asserting that no symbol with same name exists in scope
- *
- * @param sym ...
- */
- def enterUnique(sym: Symbol) {
- assert(lookup(sym.name) == NoSymbol)
- enter(sym)
- }
-
- private def createHash() {
- hashtable = new Array[ScopeEntry](HASHSIZE)
- enterInHash(elems)
- }
-
- private def enterInHash(e: ScopeEntry) {
- if (e ne null) {
- enterInHash(e.next)
- val i = e.sym.name.start & HASHMASK
- e.tail = hashtable(i)
- hashtable(i) = e
- }
- }
-
- def rehash(sym: Symbol, newname: Name) {
- if (hashtable ne null) {
- val index = sym.name.start & HASHMASK
- var e1 = hashtable(index)
- var e: ScopeEntry = null
- if (e1 != null) {
- if (e1.sym == sym) {
- hashtable(index) = e1.tail
- e = e1
- } else {
- while (e1.tail != null && e1.tail.sym != sym) e1 = e1.tail
- if (e1.tail != null) {
- e = e1.tail
- e1.tail = e.tail
- }
- }
- }
- if (e != null) {
- val newindex = newname.start & HASHMASK
- e.tail = hashtable(newindex)
- hashtable(newindex) = e
- }
- }
- }
-
- /** remove entry
- *
- * @param e ...
- */
- def unlink(e: ScopeEntry) {
- if (elems == e) {
- elems = e.next
- } else {
- var e1 = elems
- while (e1.next != e) e1 = e1.next
- e1.next = e.next
- }
- if (hashtable ne null) {
- val index = e.sym.name.start & HASHMASK
- var e1 = hashtable(index)
- if (e1 == e) {
- hashtable(index) = e.tail
- } else {
- while (e1.tail != e) e1 = e1.tail;
- e1.tail = e.tail
- }
- }
- elemsCache = null
- }
-
- /** remove symbol */
- def unlink(sym: Symbol) {
- var e = lookupEntry(sym.name)
- while (e ne null) {
- if (e.sym == sym) unlink(e);
- e = lookupNextEntry(e)
- }
- }
-
- /** lookup a symbol
- *
- * @param name ...
- * @return ...
- */
- def lookup(name: Name): Symbol = {
- val e = lookupEntry(name)
- if (e eq null) NoSymbol else e.sym
- }
-
- /** Returns an iterator yielding every symbol with given name in this scope.
- */
- def lookupAll(name: Name): Iterator[Symbol] = new Iterator[Symbol] {
- var e = lookupEntry(name)
- def hasNext: Boolean = e ne null
- def next: Symbol = { val r = e.sym; e = lookupNextEntry(e); r }
- }
-
- /** lookup a symbol entry matching given name.
- * @note from Martin: I believe this is a hotspot or will be one
- * in future versions of the type system. I have reverted the previous
- * change to use iterators as too costly.
- */
- def lookupEntry(name: Name): ScopeEntry = {
- var e: ScopeEntry = null
- if (hashtable ne null) {
- e = hashtable(name.start & HASHMASK)
- while ((e ne null) && e.sym.name != name) {
- e = e.tail
- }
- } else {
- e = elems
- while ((e ne null) && e.sym.name != name) {
- e = e.next
- }
- }
- e
- }
-
- /** lookup next entry with same name as this one
- * @note from Martin: I believe this is a hotspot or will be one
- * in future versions of the type system. I have reverted the previous
- * change to use iterators as too costly.
- */
- def lookupNextEntry(entry: ScopeEntry): ScopeEntry = {
- var e = entry
- if (hashtable ne null)
- do { e = e.tail } while ((e ne null) && e.sym.name != entry.sym.name)
- else
- do { e = e.next } while ((e ne null) && e.sym.name != entry.sym.name);
- e
- }
-
- /** Return all symbols as a list in the order they were entered in this scope.
- */
- override def toList: List[Symbol] = {
- if (elemsCache eq null) {
- elemsCache = Nil
- var e = elems
- while ((e ne null) && e.owner == this) {
- elemsCache = e.sym :: elemsCache
- e = e.next
- }
- }
- elemsCache
- }
-
- /** Return the nesting level of this scope, i.e. the number of times this scope
- * was nested in another */
- def nestingLevel = nestinglevel
-
- /** Return all symbols as an iterator in the order they were entered in this scope.
- */
- def iterator: Iterator[Symbol] = toList.iterator
-
-/*
- /** Does this scope contain an entry for `sym`?
- */
- def contains(sym: Symbol): Boolean = lookupAll(sym.name) contains sym
-
- /** A scope that contains all symbols of this scope and that also contains `sym`.
- */
- def +(sym: Symbol): Scope =
- if (contains(sym)) this
- else {
- val result = cloneScope
- result enter sym
- result
- }
-
- /** A scope that contains all symbols of this scope except `sym`.
- */
- def -(sym: Symbol): Scope =
- if (!contains(sym)) this
- else {
- val result = cloneScope
- result unlink sym
- result
- }
-*/
- override def foreach[U](p: Symbol => U): Unit = toList foreach p
-
- override def filter(p: Symbol => Boolean): Scope =
- if (!(toList forall p)) new Scope(toList filter p) else this
-
- override def mkString(start: String, sep: String, end: String) =
- toList.map(_.defString).mkString(start, sep, end)
-
- override def toString(): String = mkString("Scope{\n ", ";\n ", "\n}")
-
- }
-
- def newScope: Scope = new Scope
-
- /** The empty scope (immutable).
- */
- object EmptyScope extends Scope {
- override def enter(e: ScopeEntry) {
- abort("EmptyScope.enter")
- }
- }
-
- /** The error scope.
- */
- class ErrorScope(owner: Symbol) extends Scope(null: ScopeEntry)
-}
-
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 4a7f52f2b5..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -1,589 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-
-import scala.collection.immutable
-
-trait StdNames extends reflect.generic.StdNames with NameManglers {
- self: SymbolTable =>
-
- /** This should be the first trait in the linearization. */
- trait CompilerKeywords {
- private var kws: Set[TermName] = Set()
- private def kw(s: String): TermName = {
- val result = newTermName(s)
- kws = kws + result
- result
- }
-
- final val ABSTRACTkw: TermName = kw("abstract")
- final val CASEkw: TermName = kw("case")
- final val CLASSkw: TermName = kw("class")
- final val CATCHkw: TermName = kw("catch")
- final val DEFkw: TermName = kw("def")
- final val DOkw: TermName = kw("do")
- final val ELSEkw: TermName = kw("else")
- final val EXTENDSkw: TermName = kw("extends")
- final val FALSEkw: TermName = kw("false")
- final val FINALkw: TermName = kw("final")
- final val FINALLYkw: TermName = kw("finally")
- final val FORkw: TermName = kw("for")
- final val FORSOMEkw: TermName = kw("forSome")
- final val IFkw: TermName = kw("if")
- final val IMPLICITkw: TermName = kw("implicit")
- final val IMPORTkw: TermName = kw("import")
- final val LAZYkw: TermName = kw("lazy")
- final val MATCHkw: TermName = kw("match")
- final val NEWkw: TermName = kw("new")
- final val NULLkw: TermName = kw("null")
- final val OBJECTkw: TermName = kw("object")
- final val OVERRIDEkw: TermName = kw("override")
- final val PACKAGEkw: TermName = kw("package")
- final val PRIVATEkw: TermName = kw("private")
- final val PROTECTEDkw: TermName = kw("protected")
- final val RETURNkw: TermName = kw("return")
- final val SEALEDkw: TermName = kw("sealed")
- final val SUPERkw: TermName = kw("super")
- final val THISkw: TermName = kw("this")
- final val THROWkw: TermName = kw("throw")
- final val TRAITkw: TermName = kw("trait")
- final val TRUEkw: TermName = kw("true")
- final val TRYkw: TermName = kw("try")
- final val TYPEkw: TermName = kw("type")
- final val VALkw: TermName = kw("val")
- final val VARkw: TermName = kw("var")
- final val WITHkw: TermName = kw("with")
- final val WHILEkw: TermName = kw("while")
- final val YIELDkw: TermName = kw("yield")
- final val DOTkw: TermName = kw(".")
- final val USCOREkw: TermName = kw("_")
- final val COLONkw: TermName = kw(":")
- final val EQUALSkw: TermName = kw("=")
- final val ARROWkw: TermName = kw("=>")
- final val LARROWkw: TermName = kw("<-")
- final val SUBTYPEkw: TermName = kw("<:")
- final val VIEWBOUNDkw: TermName = kw("<%")
- final val SUPERTYPEkw: TermName = kw(">:")
- final val HASHkw: TermName = kw("#")
- final val ATkw: TermName = kw("@")
-
- final val keywords = {
- val result = kws.toSet
- kws = null
- result
- }
-
- final val javaKeywords = new JavaKeywords()
- }
-
- trait CompilerCommonNames extends LibraryCommonNames {
- // value types are all used as terms as well
- final val Boolean: NameType = "Boolean"
- final val Byte: NameType = "Byte"
- final val Char: NameType = "Char"
- final val Double: NameType = "Double"
- final val Float: NameType = "Float"
- final val Int: NameType = "Int"
- final val Long: NameType = "Long"
- final val Short: NameType = "Short"
- final val Unit: NameType = "Unit"
-
- final val ScalaValueNames: scala.List[NameType] =
- scala.List(Byte, Char, Short, Int, Long, Float, Double, Boolean, Unit)
-
- // types whose companions we utilize
- final val Array: NameType = "Array"
- final val List: NameType = "List"
- final val Seq: NameType = "Seq"
- final val Symbol: NameType = "Symbol"
-
- // fictions we use as both types and terms
- final val ERROR: NameType = "<error>"
- final val NO_NAME: NameType = "<none>" // formerly NOSYMBOL
- final val WILDCARD: NameType = "_"
- }
-
- trait CompilerTypeNames extends CompilerCommonNames {
- final val BYNAME_PARAM_CLASS_NAME: NameType = "<byname>"
- final val EQUALS_PATTERN_NAME: NameType = "<equals>"
- final val JAVA_REPEATED_PARAM_CLASS_NAME: NameType = "<repeated...>"
- final val LOCAL_CHILD: NameType = "<local child>"
- final val REPEATED_PARAM_CLASS_NAME: NameType = "<repeated>"
- final val WILDCARD_STAR: NameType = "_*"
-
- final val Any: NameType = "Any"
- final val AnyRef: NameType = "AnyRef"
- final val AnyVal: NameType = "AnyVal"
- final val Nothing: NameType = "Nothing"
- final val Null: NameType = "Null"
- final val Object: NameType = "Object"
- final val PartialFunction: NameType = "PartialFunction"
- final val Product: NameType = "Product"
- final val ScalaObject: NameType = "ScalaObject"
- final val Serializable: NameType = "Serializable"
- final val Singleton: NameType = "Singleton"
- final val String: NameType = "String"
- final val Throwable: NameType = "Throwable"
-
- // Annotation types
- final val AnnotationDefaultATTR: NameType = "AnnotationDefault"
- final val BridgeATTR: NameType = "Bridge"
- final val ClassfileAnnotationATTR: NameType = "RuntimeInvisibleAnnotations" // RetentionPolicy.CLASS. Currently not used (Apr 2009).
- final val CodeATTR: NameType = "Code"
- final val ConstantValueATTR: NameType = "ConstantValue"
- final val DeprecatedATTR: NameType = "Deprecated"
- final val ExceptionsATTR: NameType = "Exceptions"
- final val InnerClassesATTR: NameType = "InnerClasses"
- final val JacoMetaATTR: NameType = "JacoMeta"
- final val LineNumberTableATTR: NameType = "LineNumberTable"
- final val LocalVariableTableATTR: NameType = "LocalVariableTable"
- final val RuntimeAnnotationATTR: NameType = "RuntimeVisibleAnnotations" // RetentionPolicy.RUNTIME
- final val RuntimeParamAnnotationATTR: NameType = "RuntimeVisibleParameterAnnotations" // RetentionPolicy.RUNTIME (annotations on parameters)
- final val ScalaATTR: NameType = "Scala"
- final val ScalaSignatureATTR: NameType = "ScalaSig"
- final val SignatureATTR: NameType = "Signature"
- final val SourceFileATTR: NameType = "SourceFile"
- final val SyntheticATTR: NameType = "Synthetic"
- }
-
-
- trait CompilerTermNames extends CompilerKeywords with CompilerCommonNames {
- // Compiler internal names
- val ANYNAME: NameType = "<anyname>"
- val CONSTRUCTOR: NameType = "<init>"
- val FAKE_LOCAL_THIS: NameType = "this$"
- val INITIALIZER: NameType = CONSTRUCTOR // Is this buying us something?
- val MIXIN_CONSTRUCTOR: NameType = "$init$"
- val MODULE_INSTANCE_FIELD: NameType = "MODULE$"
- val OUTER: NameType = "$outer"
- val OUTER_LOCAL: NameType = "$outer " // note the space
- val SELF: NameType = "$this"
- val SPECIALIZED_INSTANCE: NameType = "specInstance$"
- val STAR: NameType = "*"
- val THIS: NameType = "_$this"
-
- final val Nil: NameType = "Nil"
- final val Predef: NameType = "Predef"
- final val ScalaRunTime: NameType = "ScalaRunTime"
- final val Some: NameType = "Some"
-
- // Compiler utilized names
- // val productElementName: NameType = "productElementName"
- val TYPE_ : NameType = "TYPE"
- val add_ : NameType = "add"
- val apply: NameType = "apply"
- val arrayValue: NameType = "arrayValue"
- val arraycopy: NameType = "arraycopy"
- val asInstanceOf_ : NameType = "asInstanceOf"
- val assert_ : NameType = "assert"
- val assume_ : NameType = "assume"
- val box: NameType = "box"
- val bytes: NameType = "bytes"
- val canEqual_ : NameType = "canEqual"
- val checkInitialized: NameType = "checkInitialized"
- val classOf: NameType = "classOf"
- val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure
- val conforms: NameType = "conforms"
- val copy: NameType = "copy"
- val delayedInit: NameType = "delayedInit"
- val delayedInitArg: NameType = "delayedInit$body"
- val drop: NameType = "drop"
- val elem: NameType = "elem"
- val eq: NameType = "eq"
- val equals_ : NameType = if (forMSIL) "Equals" else "equals"
- val error: NameType = "error"
- val ex: NameType = "ex"
- val false_ : NameType = "false"
- val filter: NameType = "filter"
- val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize"
- val find_ : NameType = "find"
- val flatMap: NameType = "flatMap"
- val foreach: NameType = "foreach"
- val genericArrayOps: NameType = "genericArrayOps"
- val get: NameType = "get"
- val hasNext: NameType = "hasNext"
- val hashCode_ : NameType = if (forMSIL) "GetHashCode" else "hashCode"
- val hash_ : NameType = "hash"
- val head: NameType = "head"
- val identity: NameType = "identity"
- val inlinedEquals: NameType = "inlinedEquals"
- val applyDynamic: NameType = "applyDynamic"
- val isArray: NameType = "isArray"
- val isDefinedAt: NameType = "isDefinedAt"
- val isEmpty: NameType = "isEmpty"
- val isInstanceOf_ : NameType = "isInstanceOf"
- val java: NameType = "java"
- val lang: NameType = "lang"
- val length: NameType = "length"
- val lengthCompare: NameType = "lengthCompare"
- val lift_ : NameType = "lift"
- val main: NameType = "main"
- val map: NameType = "map"
- val ne: NameType = "ne"
- val newArray: NameType = "newArray"
- val next: NameType = "next"
- val notifyAll_ : NameType = "notifyAll"
- val notify_ : NameType = "notify"
- val null_ : NameType = "null"
- val ofDim: NameType = "ofDim"
- val productArity: NameType = "productArity"
- val productElement: NameType = "productElement"
- val productPrefix: NameType = "productPrefix"
- val readResolve: NameType = "readResolve"
- val sameElements: NameType = "sameElements"
- val scala_ : NameType = "scala"
- val self: NameType = "self"
- val setAccessible: NameType = "setAccessible"
- val synchronized_ : NameType = "synchronized"
- val tail: NameType = "tail"
- val this_ : NameType = "this"
- val throw_ : NameType = "throw"
- val toArray: NameType = "toArray"
- val toList: NameType = "toList"
- val toSeq: NameType = "toSeq"
- val toString_ : NameType = if (forMSIL) "ToString" else "toString"
- val true_ : NameType = "true"
- val unapply: NameType = "unapply"
- val unapplySeq: NameType = "unapplySeq"
- val unbox: NameType = "unbox"
- val update: NameType = "update"
- val value: NameType = "value"
- val view_ : NameType = "view"
- val wait_ : NameType = "wait"
- val withFilter: NameType = "withFilter"
- val wrapRefArray: NameType = "wrapRefArray"
- val zip: NameType = "zip"
-
- // unencoded operators
- object raw {
- final val AMP : NameType = "&"
- final val BANG : NameType = "!"
- final val BAR : NameType = "|"
- final val DOLLAR: NameType = "$"
- final val GE: NameType = ">="
- final val LE: NameType = "<="
- final val MINUS: NameType = "-"
- final val NE: NameType = "!="
- final val PLUS : NameType = "+"
- final val SLASH: NameType = "/"
- final val STAR : NameType = "*"
- final val TILDE: NameType = "~"
-
- final val isUnary: Set[Name] = Set(MINUS, PLUS, TILDE, BANG)
- }
-
- // value-conversion methods
- val toByte: NameType = "toByte"
- val toShort: NameType = "toShort"
- val toChar: NameType = "toChar"
- val toInt: NameType = "toInt"
- val toLong: NameType = "toLong"
- val toFloat: NameType = "toFloat"
- val toDouble: NameType = "toDouble"
- }
-
- object tpnme extends CompilerTypeNames with LibraryTypeNames with TypeNameMangling {
- type NameType = TypeName
- implicit def createNameType(name: String): TypeName = newTypeName(name)
- }
-
- val javanme = nme.javaKeywords
-
- object nme extends CompilerTermNames with LibraryTermNames with TermNameMangling {
- type NameType = TermName
- implicit def createNameType(name: String): TermName = newTermName(name)
-
- /** Translate a String into a list of simple TypeNames and TermNames.
- * In all segments before the last, type/term is determined by whether
- * the following separator char is '.' or '#'. In the last segment,
- * the argument "assumeTerm" determines it. Examples:
- *
- * package foo {
- * object Lorax { object Wog ; class Wog }
- * class Lorax { object Zax ; class Zax }
- * }
- *
- * f("foo.Lorax", true) == List("foo": Term, "Lorax": Term) // object Lorax
- * f("foo.Lorax", false) == List("foo": Term, "Lorax": Type) // class Lorax
- * f("Lorax.Wog", true) == List("Lorax": Term, "Wog": Term) // object Wog
- * f("Lorax.Wog", false) == List("Lorax": Term, "Wog": Type) // class Wog
- * f("Lorax#Zax", true) == List("Lorax": Type, "Zax": Term) // object Zax
- * f("Lorax#Zax", false) == List("Lorax": Type, "Zax": Type) // class Zax
- *
- * Note that in actual scala syntax you cannot refer to object Zax without an
- * instance of Lorax, so Lorax#Zax could only mean the type. One might think
- * that Lorax#Zax.type would work, but this is not accepted by the parser.
- * For the purposes of referencing that object, the syntax is allowed.
- */
- def segments(name: String, assumeTerm: Boolean): List[Name] = {
- def mkName(str: String, term: Boolean): Name =
- if (term) newTermName(str) else newTypeName(str)
-
- name.indexWhere(ch => ch == '.' || ch == '#') match {
- // it's the last segment: the parameter tells us whether type or term
- case -1 => if (name == "") scala.Nil else scala.List(mkName(name, assumeTerm))
- // otherwise, we can tell based on whether '#' or '.' is the following char.
- case idx =>
- val (simple, div, rest) = (name take idx, name charAt idx, name drop (idx + 1))
- mkName(simple, div == '.') :: segments(rest, assumeTerm)
- }
- }
- private def bitmapName(n: Int, suffix: String): TermName =
- newTermName(BITMAP_PREFIX + suffix + n)
-
- /** The name of bitmaps for initialized (public or protected) lazy vals. */
- def bitmapName(n: Int): TermName = bitmapName(n, "")
-
- /** The name of bitmaps for initialized transient lazy vals. */
- def bitmapNameForTransient(n: Int): TermName = bitmapName(n, "trans$")
-
- /** The name of bitmaps for initialized private lazy vals. */
- def bitmapNameForPrivate(n: Int): TermName = bitmapName(n, "priv$")
-
- /** The name of bitmaps for checkinit values */
- def bitmapNameForCheckinit(n: Int): TermName = bitmapName(n, "init$")
-
- /** The name of bitmaps for checkinit values that have transient flag*/
- def bitmapNameForCheckinitTransient(n: Int): TermName = bitmapName(n, "inittrans$")
-
- /** Base strings from which synthetic names are derived. */
- val BITMAP_PREFIX = "bitmap$"
- val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$"
- val DEFAULT_GETTER_STRING = "$default$"
- val DO_WHILE_PREFIX = "doWhile$"
- val EQEQ_LOCAL_VAR = "eqEqTemp$"
- val EVIDENCE_PARAM_PREFIX = "evidence$"
- val EXCEPTION_RESULT_PREFIX = "exceptionResult"
- val INTERPRETER_IMPORT_WRAPPER = "$iw"
- val INTERPRETER_LINE_PREFIX = "line"
- val INTERPRETER_SYNTHVAR_PREFIX = "synthvar$"
- val INTERPRETER_VAR_PREFIX = "res"
- val INTERPRETER_WRAPPER_SUFFIX = "$object"
- val WHILE_PREFIX = "while$"
-
- def getCause = sn.GetCause
- def getClass_ = sn.GetClass
- def getMethod_ = sn.GetMethod
- def invoke_ = sn.Invoke
-
- val ADD = encode("+")
- val AND = encode("&")
- val ASR = encode(">>")
- val DIV = encode("/")
- val EQ = encode("==")
- val EQL = encode("=")
- val GE = encode(">=")
- val GT = encode(">")
- val HASHHASH = encode("##")
- val LE = encode("<=")
- val LSL = encode("<<")
- val LSR = encode(">>>")
- val LT = encode("<")
- val MINUS = encode("-")
- val MOD = encode("%")
- val MUL = encode("*")
- val NE = encode("!=")
- val OR = encode("|")
- val PLUS = encode("+")
- val SUB = encode("-")
- val XOR = encode("^")
- val ZAND = encode("&&")
- val ZOR = encode("||")
-
- // unary operators
- val UNARY_~ = encode("unary_~")
- val UNARY_+ = encode("unary_+")
- val UNARY_- = encode("unary_-")
- val UNARY_! = encode("unary_!")
- }
-
- abstract class SymbolNames {
- protected implicit def stringToTypeName(s: String): TypeName = newTypeName(s)
-
- val BeanProperty : TypeName
- val BooleanBeanProperty : TypeName
- val BoxedBoolean : TypeName
- val BoxedCharacter : TypeName
- val BoxedNumber : TypeName
- val Class : TypeName
- val Code : TypeName
- val Delegate : TypeName
- val IOOBException : TypeName // IndexOutOfBoundsException
- val InvTargetException : TypeName // InvocationTargetException
- val JavaSerializable : TypeName
- val MethodAsObject : TypeName
- val NPException : TypeName // NullPointerException
- val Object : TypeName
- val String : TypeName
- val Throwable : TypeName
- val ValueType : TypeName
-
- val ForName : TermName
- val GetCause : TermName
- val GetClass : TermName
- val GetMethod : TermName
- val Invoke : TermName
- val JavaLang : TermName
-
- val Boxed: immutable.Map[TypeName, TypeName]
- }
-
- class JavaKeywords {
- private var kws: Set[TermName] = Set()
- private def kw(s: String): TermName = {
- val result = newTermName(s)
- kws = kws + result
- result
- }
-
- final val ABSTRACTkw: TermName = kw("abstract")
- final val ASSERTkw: TermName = kw("assert")
- final val BOOLEANkw: TermName = kw("boolean")
- final val BREAKkw: TermName = kw("break")
- final val BYTEkw: TermName = kw("byte")
- final val CASEkw: TermName = kw("case")
- final val CATCHkw: TermName = kw("catch")
- final val CHARkw: TermName = kw("char")
- final val CLASSkw: TermName = kw("class")
- final val CONSTkw: TermName = kw("const")
- final val CONTINUEkw: TermName = kw("continue")
- final val DEFAULTkw: TermName = kw("default")
- final val DOkw: TermName = kw("do")
- final val DOUBLEkw: TermName = kw("double")
- final val ELSEkw: TermName = kw("else")
- final val ENUMkw: TermName = kw("enum")
- final val EXTENDSkw: TermName = kw("extends")
- final val FINALkw: TermName = kw("final")
- final val FINALLYkw: TermName = kw("finally")
- final val FLOATkw: TermName = kw("float")
- final val FORkw: TermName = kw("for")
- final val IFkw: TermName = kw("if")
- final val GOTOkw: TermName = kw("goto")
- final val IMPLEMENTSkw: TermName = kw("implements")
- final val IMPORTkw: TermName = kw("import")
- final val INSTANCEOFkw: TermName = kw("instanceof")
- final val INTkw: TermName = kw("int")
- final val INTERFACEkw: TermName = kw("interface")
- final val LONGkw: TermName = kw("long")
- final val NATIVEkw: TermName = kw("native")
- final val NEWkw: TermName = kw("new")
- final val PACKAGEkw: TermName = kw("package")
- final val PRIVATEkw: TermName = kw("private")
- final val PROTECTEDkw: TermName = kw("protected")
- final val PUBLICkw: TermName = kw("public")
- final val RETURNkw: TermName = kw("return")
- final val SHORTkw: TermName = kw("short")
- final val STATICkw: TermName = kw("static")
- final val STRICTFPkw: TermName = kw("strictfp")
- final val SUPERkw: TermName = kw("super")
- final val SWITCHkw: TermName = kw("switch")
- final val SYNCHRONIZEDkw: TermName = kw("synchronized")
- final val THISkw: TermName = kw("this")
- final val THROWkw: TermName = kw("throw")
- final val THROWSkw: TermName = kw("throws")
- final val TRANSIENTkw: TermName = kw("transient")
- final val TRYkw: TermName = kw("try")
- final val VOIDkw: TermName = kw("void")
- final val VOLATILEkw: TermName = kw("volatile")
- final val WHILEkw: TermName = kw("while")
-
- final val keywords = {
- val result = kws.toSet
- kws = null
- result
- }
- }
-
- private abstract class JavaNames extends SymbolNames {
- final val BoxedBoolean: TypeName = "java.lang.Boolean"
- final val BoxedByte: TypeName = "java.lang.Byte"
- final val BoxedCharacter: TypeName = "java.lang.Character"
- final val BoxedDouble: TypeName = "java.lang.Double"
- final val BoxedFloat: TypeName = "java.lang.Float"
- final val BoxedInteger: TypeName = "java.lang.Integer"
- final val BoxedLong: TypeName = "java.lang.Long"
- final val BoxedNumber: TypeName = "java.lang.Number"
- final val BoxedShort: TypeName = "java.lang.Short"
- final val Class: TypeName = "java.lang.Class"
- final val Delegate: TypeName = tpnme.NO_NAME
- final val IOOBException: TypeName = "java.lang.IndexOutOfBoundsException"
- final val InvTargetException: TypeName = "java.lang.reflect.InvocationTargetException"
- final val MethodAsObject: TypeName = "java.lang.reflect.Method"
- final val NPException: TypeName = "java.lang.NullPointerException"
- final val Object: TypeName = "java.lang.Object"
- final val String: TypeName = "java.lang.String"
- final val Throwable: TypeName = "java.lang.Throwable"
- final val ValueType: TypeName = tpnme.NO_NAME
-
- final val ForName: TermName = "forName"
- final val GetCause: TermName = "getCause"
- final val GetClass: TermName = "getClass"
- final val GetMethod: TermName = "getMethod"
- final val Invoke: TermName = "invoke"
- final val JavaLang: TermName = "java.lang"
-
- val Boxed = immutable.Map[TypeName, TypeName](
- tpnme.Boolean -> BoxedBoolean,
- tpnme.Byte -> BoxedByte,
- tpnme.Char -> BoxedCharacter,
- tpnme.Short -> BoxedShort,
- tpnme.Int -> BoxedInteger,
- tpnme.Long -> BoxedLong,
- tpnme.Float -> BoxedFloat,
- tpnme.Double -> BoxedDouble
- )
- }
-
- private class MSILNames extends SymbolNames {
- final val BeanProperty: TypeName = tpnme.NO_NAME
- final val BooleanBeanProperty: TypeName = tpnme.NO_NAME
- final val BoxedBoolean: TypeName = "System.IConvertible"
- final val BoxedCharacter: TypeName = "System.IConvertible"
- final val BoxedNumber: TypeName = "System.IConvertible"
- final val Class: TypeName = "System.Type"
- final val Code: TypeName = tpnme.NO_NAME
- final val Delegate: TypeName = "System.MulticastDelegate"
- final val IOOBException: TypeName = "System.IndexOutOfRangeException"
- final val InvTargetException: TypeName = "System.Reflection.TargetInvocationException"
- final val JavaSerializable: TypeName = tpnme.NO_NAME
- final val MethodAsObject: TypeName = "System.Reflection.MethodInfo"
- final val NPException: TypeName = "System.NullReferenceException"
- final val Object: TypeName = "System.Object"
- final val String: TypeName = "System.String"
- final val Throwable: TypeName = "System.Exception"
- final val ValueType: TypeName = "System.ValueType"
-
- final val ForName: TermName = "GetType"
- final val GetCause: TermName = "InnerException" /* System.Reflection.TargetInvocationException.InnerException */
- final val GetClass: TermName = "GetType"
- final val GetMethod: TermName = "GetMethod"
- final val Invoke: TermName = "Invoke"
- final val JavaLang: TermName = "System"
-
- val Boxed = immutable.Map[TypeName, TypeName](
- tpnme.Boolean -> "System.Boolean",
- tpnme.Byte -> "System.SByte", // a scala.Byte is signed and a System.SByte too (unlike a System.Byte)
- tpnme.Char -> "System.Char",
- tpnme.Short -> "System.Int16",
- tpnme.Int -> "System.Int32",
- tpnme.Long -> "System.Int64",
- tpnme.Float -> "System.Single",
- tpnme.Double -> "System.Double"
- )
- }
-
- private class J2SENames extends JavaNames {
- final val BeanProperty: TypeName = "scala.reflect.BeanProperty"
- final val BooleanBeanProperty: TypeName = "scala.reflect.BooleanBeanProperty"
- final val Code: TypeName = "scala.reflect.Code"
- final val JavaSerializable: TypeName = "java.io.Serializable"
- }
-
- lazy val sn: SymbolNames =
- if (forMSIL) new MSILNames
- else new J2SENames
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 3536e79a76..9f91d89158 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -10,10 +10,9 @@ import java.io.IOException
import ch.epfl.lamp.compiler.msil.{ Type => MSILType, Attribute => MSILAttribute }
import scala.compat.Platform.currentTime
-import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.util.{ ClassPath }
import classfile.ClassfileParser
-import Flags._
+import reflect.common.Flags._
import util.Statistics._
/** This class ...
@@ -285,7 +284,7 @@ abstract class SymbolLoaders {
classfileParser.parse(classfile, root)
stopTimer(classReadNanos, start)
}
- override def sourcefile = classfileParser.srcfile
+ override def sourcefile: Option[AbstractFile] = classfileParser.srcfile
}
class MSILTypeLoader(typ: MSILType) extends SymbolLoader {
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index d3decb0abc..d27374cc29 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -10,107 +10,4 @@ import ast.{Trees, TreePrinters, DocComments}
import util._
-abstract class SymbolTable extends reflect.generic.Universe
- with Names
- with Symbols
- with Types
- with Scopes
- with Caches
- with Definitions
- with reflect.generic.Constants
- with BaseTypeSeqs
- with InfoTransformers
- with StdNames
- with AnnotationInfos
- with AnnotationCheckers
- with Trees
- with TreePrinters
- with Positions
- with DocComments
- with TypeDebugging
-{
- def settings: Settings
- def rootLoader: LazyType
- def log(msg: => AnyRef)
- def abort(msg: String) = throw new Error(msg)
- def abort() = throw new Error()
-
- /** Are we compiling for Java SE ? */
- def forJVM: Boolean
-
- /** Are we compiling for .NET ? */
- def forMSIL: Boolean
-
- /** A period is an ordinal number for a phase in a run.
- * Phases in later runs have higher periods than phases in earlier runs.
- * Later phases have higher periods than earlier phases in the same run.
- */
- type Period = Int
- final val NoPeriod = 0
-
- /** An ordinal number for compiler runs. First run has number 1. */
- type RunId = Int
- final val NoRunId = 0
-
- private var ph: Phase = NoPhase
- private var per = NoPeriod
-
- final def phase: Phase = ph
-
- final def phase_=(p: Phase) {
- //System.out.println("setting phase to " + p)
- assert((p ne null) && p != NoPhase)
- ph = p
- per = (currentRunId << 8) + p.id
- }
-
- /** The current compiler run identifier. */
- def currentRunId: RunId
-
- /** The run identifier of the given period */
- final def runId(period: Period): RunId = period >> 8
-
- /** The phase identifier of the given period */
- final def phaseId(period: Period): Phase#Id = period & 0xFF
-
- /** The period at the start of run that includes `period' */
- final def startRun(period: Period): Period = period & 0xFFFFFF00
-
- /** The current period */
- final def currentPeriod: Period = {
- //assert(per == (currentRunId << 8) + phase.id)
- per
- }
-
- /** The phase associated with given period */
- final def phaseOf(period: Period): Phase = phaseWithId(phaseId(period))
-
- final def period(rid: RunId, pid: Phase#Id): Period =
- (currentRunId << 8) + pid
-
- /** Perform given operation at given phase */
- final def atPhase[T](ph: Phase)(op: => T): T = {
- // Eugene: insert same thread assertion here
- val current = phase
- phase = ph
- try op
- finally phase = current
- }
- final def afterPhase[T](ph: Phase)(op: => T): T =
- atPhase(ph.next)(op)
-
- /** Break into repl debugger if assertion is true */
- // def breakIf(assertion: => Boolean, args: Any*): Unit =
- // if (assertion)
- // ILoop.break(args.toList)
-
- /** The set of all installed infotransformers */
- var infoTransformers = new InfoTransformer {
- val pid = NoPhase.id
- val changesBaseClasses = true
- def transform(sym: Symbol, tpe: Type): Type = tpe
- }
-
- /** The phase which has given index as identifier */
- val phaseWithId: Array[Phase]
-}
+abstract class SymbolTable extends reflect.common.SymbolTable
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index d1f5cbf4d2..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -1,2181 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-
-package scala.tools.nsc
-package symtab
-
-import scala.collection.{ mutable, immutable }
-import scala.collection.mutable.ListBuffer
-import io.AbstractFile
-import util.{ Position, NoPosition, BatchSourceFile }
-import util.Statistics._
-import Flags._
-
-trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
- import definitions._
-
- private var ids = 0
- def symbolCount = ids // statistics
-
- val emptySymbolArray = new Array[Symbol](0)
-
- /** Used for deciding in the IDE whether we can interrupt the compiler */
- //protected var activeLocks = 0
-
- /** Used for debugging only */
- //protected var lockedSyms = collection.immutable.Set[Symbol]()
-
- /** Used to keep track of the recursion depth on locked symbols */
- private var recursionTable = immutable.Map.empty[Symbol, Int]
-
- private var nextexid = 0
- private def freshExistentialName(suffix: String) = {
- nextexid += 1
- newTypeName("_" + nextexid + suffix)
- }
-
- /** The original owner of a class. Used by the backend to generate
- * EnclosingMethod attributes.
- */
- val originalOwner = mutable.HashMap[Symbol, Symbol]()
-
- /** The class for all symbols */
- abstract class Symbol(initOwner: Symbol, initPos: Position, initName: Name) extends AbsSymbol {
- var rawowner = initOwner
- var rawname = initName
- var rawflags = 0L
-
- private var rawpos = initPos
- val id = { ids += 1; ids } // identity displayed when -uniqid
-
- var validTo: Period = NoPeriod
-
- def pos = rawpos
- def setPos(pos: Position): this.type = { this.rawpos = pos; this }
-
-// annotations
-
- private var rawannots: List[AnnotationInfoBase] = Nil
- def rawAnnotations = rawannots
-
- /* Used in namer to check whether annotations were already assigned or not */
- def hasAssignedAnnotations = rawannots.nonEmpty
-
- /** After the typer phase (before, look at the definition's Modifiers), contains
- * the annotations attached to member a definition (class, method, type, field).
- */
- def annotations: List[AnnotationInfo] = {
- // .initialize: the type completer of the symbol parses the annotations,
- // see "def typeSig" in Namers
- val annots1 = initialize.rawannots map {
- case x: LazyAnnotationInfo => x.annot()
- case x: AnnotationInfo => x
- } filterNot (_.atp.isError)
- rawannots = annots1
- annots1
- }
-
- def setAnnotations(annots: List[AnnotationInfoBase]): this.type = {
- this.rawannots = annots
- this
- }
-
- override def addAnnotation(annot: AnnotationInfo) {
- setAnnotations(annot :: this.rawannots)
- }
-
- /** Does this symbol have an annotation of the given class? */
- def hasAnnotation(cls: Symbol) =
- getAnnotation(cls).isDefined
-
- def getAnnotation(cls: Symbol): Option[AnnotationInfo] =
- annotations find (_.atp.typeSymbol == cls)
-
- /** Remove all annotations matching the given class. */
- def removeAnnotation(cls: Symbol): Unit =
- setAnnotations(annotations filterNot (_.atp.typeSymbol == cls))
-
- /** See comment in HasFlags for how privateWithin combines with flags.
- */
- private[this] var _privateWithin: Symbol = _
- def privateWithin = _privateWithin
- override def privateWithin_=(sym: Symbol) { _privateWithin = sym }
-
-// Creators -------------------------------------------------------------------
-
- final def newValue(pos: Position, name: TermName) =
- new TermSymbol(this, pos, name)
- final def newValue(name: TermName, pos: Position = NoPosition) =
- new TermSymbol(this, pos, name)
- final def newVariable(pos: Position, name: TermName) =
- newValue(pos, name).setFlag(MUTABLE)
- final def newValueParameter(pos: Position, name: TermName) =
- newValue(pos, name).setFlag(PARAM)
- /** Create local dummy for template (owner of local blocks) */
- final def newLocalDummy(pos: Position) =
- newValue(pos, nme.localDummyName(this)).setInfo(NoType)
- final def newMethod(pos: Position, name: TermName) =
- new MethodSymbol(this, pos, name).setFlag(METHOD)
- final def newMethod(name: TermName, pos: Position = NoPosition) =
- new MethodSymbol(this, pos, name).setFlag(METHOD)
- final def newLabel(pos: Position, name: TermName) =
- newMethod(pos, name).setFlag(LABEL)
- final def newConstructor(pos: Position) =
- newMethod(pos, nme.CONSTRUCTOR)
- final def newModule(pos: Position, name: TermName, clazz: ClassSymbol) =
- new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- .setModuleClass(clazz)
- final def newModule(name: TermName, clazz: Symbol, pos: Position = NoPosition) =
- new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- .setModuleClass(clazz.asInstanceOf[ClassSymbol])
- final def newModule(pos: Position, name: TermName) = {
- val m = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- m.setModuleClass(new ModuleClassSymbol(m))
- }
- final def newPackage(pos: Position, name: TermName) = {
- assert(name == nme.ROOT || isPackageClass)
- val m = newModule(pos, name).setFlag(JAVA | PACKAGE)
- m.moduleClass.setFlag(JAVA | PACKAGE)
- m
- }
- final def newThisSym(pos: Position) =
- newValue(pos, nme.this_).setFlag(SYNTHETIC)
- final def newImport(pos: Position) =
- newValue(pos, nme.IMPORT)
-
- /** @param pre type relative to which alternatives are seen.
- * for instance:
- * class C[T] {
- * def m(x: T): T
- * def m'(): T
- * }
- * val v: C[Int]
- *
- * Then v.m has symbol TermSymbol(flags = {OVERLOADED},
- * tpe = OverloadedType(C[Int], List(m, m')))
- * You recover the type of m doing a
- *
- * m.tpe.asSeenFrom(pre, C) (generally, owner of m, which is C here).
- *
- * or:
- *
- * pre.memberType(m)
- */
- final def newOverloaded(pre: Type, alternatives: List[Symbol]): Symbol =
- newValue(alternatives.head.pos, alternatives.head.name.toTermName)
- .setFlag(OVERLOADED)
- .setInfo(OverloadedType(pre, alternatives))
-
- /** for explicit outer phase */
- final def newOuterAccessor(pos: Position) = {
- val sym = newMethod(pos, nme.OUTER)
- sym setFlag (STABLE | SYNTHETIC)
- if (isTrait) sym setFlag DEFERRED
- sym.expandName(this)
- sym.referenced = this
- sym
- }
-
- final def newErrorValue(name: TermName) =
- newValue(pos, name).setFlag(SYNTHETIC | IS_ERROR).setInfo(ErrorType)
-
- /** Symbol of a type definition type T = ...
- */
- final def newAliasType(pos: Position, name: TypeName) =
- new TypeSymbol(this, pos, name)
- final def newAliasType(name: TypeName, pos: Position = NoPosition) =
- new TypeSymbol(this, pos, name)
-
- /** Symbol of an abstract type type T >: ... <: ...
- */
- final def newAbstractType(pos: Position, name: TypeName) =
- new TypeSymbol(this, pos, name).setFlag(DEFERRED)
- final def newAbstractType(name: TypeName, pos: Position = NoPosition) =
- new TypeSymbol(this, pos, name).setFlag(DEFERRED)
-
- /** Symbol of a type parameter
- */
- final def newTypeParameter(pos: Position, name: TypeName) =
- newAbstractType(pos, name).setFlag(PARAM)
-
- /** Synthetic value parameters when parameter symbols are not available
- */
- final def newSyntheticValueParamss(argtypess: List[List[Type]]): List[List[Symbol]] = {
- var cnt = 0
- def freshName() = { cnt += 1; newTermName("x$" + cnt) }
- def param(tp: Type) =
- newValueParameter(owner.pos.focus, freshName()).setFlag(SYNTHETIC).setInfo(tp)
- argtypess map (_.map(param))
- }
-
- final def newExistential(pos: Position, name: TypeName): Symbol =
- newAbstractType(pos, name).setFlag(EXISTENTIAL)
-
- final def freshExistential(suffix: String): Symbol =
- newExistential(pos, freshExistentialName(suffix))
-
- /** Synthetic value parameters when parameter symbols are not available.
- * Calling this method multiple times will re-use the same parameter names.
- */
- final def newSyntheticValueParams(argtypes: List[Type]): List[Symbol] =
- newSyntheticValueParamss(List(argtypes)).head
-
- /** Synthetic value parameter when parameter symbol is not available.
- * Calling this method multiple times will re-use the same parameter name.
- */
- final def newSyntheticValueParam(argtype: Type): Symbol =
- newSyntheticValueParams(List(argtype)).head
-
- /** Type skolems are type parameters ``seen from the inside''
- * Assuming a polymorphic method m[T], its type is a PolyType which has a TypeParameter
- * with name `T' in its typeParams list. While type checking the parameters, result type and
- * body of the method, there's a local copy of `T' which is a TypeSkolem.
- */
- final def newTypeSkolem: Symbol =
- new TypeSkolem(owner, pos, name.toTypeName, this)
- .setFlag(flags)
-
- final def newClass(pos: Position, name: TypeName) =
- new ClassSymbol(this, pos, name)
- final def newClass(name: TypeName, pos: Position = NoPosition) =
- new ClassSymbol(this, pos, name)
-
- final def newModuleClass(pos: Position, name: TypeName) =
- new ModuleClassSymbol(this, pos, name)
- final def newModuleClass(name: TypeName, pos: Position = NoPosition) =
- new ModuleClassSymbol(this, pos, name)
-
- final def newAnonymousClass(pos: Position) =
- newClass(pos, tpnme.ANON_CLASS_NAME)
- final def newAnonymousFunctionClass(pos: Position) =
- newClass(pos, tpnme.ANON_FUN_NAME)
-
- /** Refinement types P { val x: String; type T <: Number }
- * also have symbols, they are refinementClasses
- */
- final def newRefinementClass(pos: Position) =
- newClass(pos, tpnme.REFINE_CLASS_NAME)
-
- /** Create a new getter for current symbol (which must be a field)
- */
- final def newGetter: Symbol = {
- val getter = owner.newMethod(pos.focus, nme.getterName(name)).setFlag(getterFlags(flags))
- getter.privateWithin = privateWithin
- getter.setInfo(MethodType(List(), tpe))
- }
-
- final def newErrorClass(name: TypeName) = {
- val clazz = newClass(pos, name).setFlag(SYNTHETIC | IS_ERROR)
- clazz.setInfo(ClassInfoType(List(), new ErrorScope(this), clazz))
- clazz
- }
-
- final def newErrorSymbol(name: Name): Symbol = name match {
- case x: TypeName => newErrorClass(x)
- case x: TermName => newErrorValue(x)
- }
-
-// Locking and unlocking ------------------------------------------------------
-
- // True if the symbol is unlocked.
- // True if the symbol is locked but still below the allowed recursion depth.
- // False otherwise
- def lockOK: Boolean = {
- ((rawflags & LOCKED) == 0L) ||
- ((settings.Yrecursion.value != 0) &&
- (recursionTable get this match {
- case Some(n) => (n <= settings.Yrecursion.value)
- case None => true }))
- }
-
- // Lock a symbol, using the handler if the recursion depth becomes too great.
- def lock(handler: => Unit) = {
- if ((rawflags & LOCKED) != 0L) {
- if (settings.Yrecursion.value != 0) {
- recursionTable get this match {
- case Some(n) =>
- if (n > settings.Yrecursion.value) {
- handler
- } else {
- recursionTable += (this -> (n + 1))
- }
- case None =>
- recursionTable += (this -> 1)
- }
- } else { handler }
- } else {
- rawflags |= LOCKED
-// activeLocks += 1
-// lockedSyms += this
- }
- }
-
- // Unlock a symbol
- def unlock() = {
- if ((rawflags & LOCKED) != 0L) {
-// activeLocks -= 1
-// lockedSyms -= this
- rawflags = rawflags & ~LOCKED
- if (settings.Yrecursion.value != 0)
- recursionTable -= this
- }
- }
-
-// Tests ----------------------------------------------------------------------
-
- /** Is this symbol a type but not a class? */
- def isNonClassType = false
-
- /** Term symbols with the exception of static parts of Java classes and packages.
- */
- final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA))
-
- final def isVariable = isTerm && isMutable && !isMethod
-
- // interesting only for lambda lift. Captured variables are accessed from inner lambdas.
- final def isCapturedVariable = isVariable && hasFlag(CAPTURED)
-
- final def isGetter = isTerm && hasAccessorFlag && !nme.isSetterName(name)
- // todo: make independent of name, as this can be forged.
- final def isSetter = isTerm && hasAccessorFlag && nme.isSetterName(name)
- def isSetterParameter = isValueParameter && owner.isSetter
-
- final def hasGetter = isTerm && nme.isLocalName(name)
-
- final def isValueParameter = isTerm && hasFlag(PARAM)
- final def isLocalDummy = isTerm && nme.isLocalDummyName(name)
- final def isInitializedToDefault = !isType && hasAllFlags(DEFAULTINIT | ACCESSOR)
- final def isClassConstructor = isTerm && (name == nme.CONSTRUCTOR)
- final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR)
- final def isConstructor = isTerm && nme.isConstructorName(name)
- final def isStaticModule = isModule && isStatic && !isMethod
- final def isThisSym = isTerm && owner.thisSym == this
- final def isError = hasFlag(IS_ERROR)
- final def isErroneous = isError || isInitialized && tpe.isErroneous
- override final def isTrait: Boolean = isClass && hasFlag(TRAIT | notDEFERRED) // A virtual class becomes a trait (part of DEVIRTUALIZE)
- final def isTypeParameterOrSkolem = isType && hasFlag(PARAM)
- final def isHigherOrderTypeParameter = owner.isTypeParameterOrSkolem
- final def isTypeSkolem = isSkolem && hasFlag(PARAM)
- // a type symbol bound by an existential type, for instance the T in
- // List[T] forSome { type T }
- final def isExistentialSkolem = isExistentiallyBound && isSkolem
- final def isExistentialQuantified = isExistentiallyBound && !isSkolem
-
- // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor
- final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
-
- final def isAnonymousClass = isClass && (name containsName tpnme.ANON_CLASS_NAME)
- final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME)
- final def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass
-
- final def isPackageObject = isModule && name == nme.PACKAGEkw && owner.isPackageClass
- final def isPackageObjectClass = isModuleClass && name.toTermName == nme.PACKAGEkw && owner.isPackageClass
- final def definedInPackage = owner.isPackageClass || owner.isPackageObjectClass
- final def isJavaInterface = isJavaDefined && isTrait
- final def needsFlatClasses: Boolean = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass
-
- // not printed as prefixes
- final def isPredefModule = this == PredefModule
- final def isScalaPackage = (this == ScalaPackage) || (isPackageObject && owner == ScalaPackageClass)
- final def isScalaPackageClass = skipPackageObject == ScalaPackageClass
-
- /** If this is a package object or package object class, its owner: otherwise this.
- */
- final def skipPackageObject: Symbol = if (isPackageObjectClass) owner else this
-
- /** If this is a constructor, its owner: otherwise this.
- */
- final def skipConstructor: Symbol = if (isConstructor) owner else this
-
- /** Conditions where we omit the prefix when printing a symbol, to avoid
- * unpleasantries like Predef.String, $iw.$iw.Foo and <empty>.Bippy.
- */
- final def printWithoutPrefix = !settings.debug.value && (
- isScalaPackageClass || isPredefModule || isEffectiveRoot || isAnonOrRefinementClass || isInterpreterWrapper
- )
-
- /** Is symbol a monomorphic type?
- * assumption: if a type starts out as monomorphic, it will not acquire
- * type parameters in later phases.
- */
- final def isMonomorphicType =
- isType && {
- var is = infos
- (is eq null) || {
- while (is.prev ne null) { is = is.prev }
- is.info.isComplete && is.info.typeParams.isEmpty
- }
- }
-
- def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr)
- def isSerializable = info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass) || hasAnnotation(SerializableAttr) // last part can be removed, @serializable annotation is deprecated
- def isDeprecated = hasAnnotation(DeprecatedAttr)
- def hasBridgeAnnotation = hasAnnotation(BridgeClass)
- def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0)
- def deprecationVersion = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 1)
- // !!! when annotation arguments are not literal strings, but any sort of
- // assembly of strings, there is a fair chance they will turn up here not as
- // Literal(const) but some arbitrary AST. However nothing in the compiler
- // prevents someone from writing a @migration annotation with a calculated
- // string. So this needs attention. For now the fact that migration is
- // private[scala] ought to provide enough protection.
- def migrationMessage = getAnnotation(MigrationAnnotationClass) flatMap { _.stringArg(2) }
- def elisionLevel = getAnnotation(ElidableMethodClass) flatMap { _.intArg(0) }
- def implicitNotFoundMsg = getAnnotation(ImplicitNotFoundClass) flatMap { _.stringArg(0) }
-
- /** Does this symbol denote a wrapper created by the repl? */
- final def isInterpreterWrapper = (isModule || isModuleClass) && nme.isReplWrapperName(name)
-
- override def isEffectiveRoot = super.isEffectiveRoot || isInterpreterWrapper
-
- /** Is this symbol an accessor method for outer? */
- final def isOuterAccessor = {
- hasFlag(STABLE | SYNTHETIC) &&
- originalName == nme.OUTER
- }
-
- /** Is this symbol an accessor method for outer? */
- final def isOuterField = {
- hasFlag(SYNTHETIC) &&
- originalName == nme.OUTER_LOCAL
- }
-
- /** Does this symbol denote a stable value? */
- final def isStable =
- isTerm &&
- !isMutable &&
- (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) &&
- !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass))
-
- def isVirtualClass =
- hasFlag(DEFERRED) && isClass
-
- def isVirtualTrait =
- hasFlag(DEFERRED) && isTrait
-
- def isLiftedMethod = isMethod && hasFlag(LIFTED)
- def isCaseClass = isClass && isCase
-
- /** Does this symbol denote the primary constructor of its enclosing class? */
- final def isPrimaryConstructor =
- isConstructor && owner.primaryConstructor == this
-
- /** Does this symbol denote an auxiliary constructor of its enclosing class? */
- final def isAuxiliaryConstructor =
- isConstructor && !isPrimaryConstructor
-
- /** Is this symbol a synthetic apply or unapply method in a companion object of a case class? */
- final def isCaseApplyOrUnapply =
- isMethod && isCase && isSynthetic
-
- /** Is this symbol a trait which needs an implementation class? */
- final def needsImplClass: Boolean =
- isTrait && (!isInterface || hasFlag(lateINTERFACE)) && !isImplClass
-
- /** Is this a symbol which exists only in the implementation class, not in its trait? */
- final def isImplOnly: Boolean =
- hasFlag(PRIVATE) ||
- (owner.isImplClass || owner.isTrait) &&
- ((hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR | MODULE) || isConstructor) ||
- (hasFlag(LIFTED) && isModule && isMethod))
-
- /** Is this symbol a module variable?
- * This used to have to test for MUTABLE to distinguish the overloaded
- * MODULEVAR/SYNTHETICMETH flag, but now SYNTHETICMETH is gone.
- */
- final def isModuleVar = hasFlag(MODULEVAR)
-
- /** Is this symbol static (i.e. with no outer instance)? */
- final def isStatic: Boolean =
- hasFlag(STATIC) || isRoot || owner.isStaticOwner
-
- /** Is this symbol a static constructor? */
- final def isStaticConstructor: Boolean =
- isStaticMember && isClassConstructor
-
- /** Is this symbol a static member of its class? (i.e. needs to be implemented as a Java static?) */
- final def isStaticMember: Boolean =
- hasFlag(STATIC) || owner.isImplClass
-
- /** Does this symbol denote a class that defines static symbols? */
- final def isStaticOwner: Boolean =
- isPackageClass || isModuleClass && isStatic
-
- /** Is this symbol effectively final? I.e, it cannot be overridden */
- final def isEffectivelyFinal: Boolean = isFinal || isTerm && (
- hasFlag(PRIVATE) || isLocal || owner.isClass && owner.hasFlag(FINAL | MODULE))
-
- /** Is this symbol locally defined? I.e. not accessed from outside `this' instance */
- final def isLocal: Boolean = owner.isTerm
-
- /** Is this symbol a constant? */
- final def isConstant: Boolean =
- isStable && (tpe match {
- case ConstantType(_) => true
- case PolyType(_, ConstantType(_)) => true
- case MethodType(_, ConstantType(_)) => true
- case NullaryMethodType(ConstantType(_)) => true
- case _ => false
- })
-
- /** Is this class nested in another class or module (not a package)? */
- final def isNestedClass: Boolean =
- isClass && !isRoot && !owner.isPackageClass
-
- /** Is this class locally defined?
- * A class is local, if
- * - it is anonymous, or
- * - its owner is a value
- * - it is defined within a local class
- */
- final def isLocalClass: Boolean =
- isClass && (isAnonOrRefinementClass || isLocal ||
- !owner.isPackageClass && owner.isLocalClass)
-
-/* code for fixing nested objects
- override final def isModuleClass: Boolean =
- super.isModuleClass && !isExpandedModuleClass
-*/
- /** Is this class or type defined as a structural refinement type?
- */
- final def isStructuralRefinement: Boolean =
- (isClass || isType || isModule) && info.normalize/*.underlying*/.isStructuralRefinement
-
-
- /** Is this symbol a member of class `clazz'
- */
- def isMemberOf(clazz: Symbol) =
- clazz.info.member(name).alternatives contains this
-
- /** A a member of class `base' is incomplete if
- * (1) it is declared deferred or
- * (2) it is abstract override and its super symbol in `base' is
- * nonexistent or incomplete.
- *
- * @param base ...
- * @return ...
- */
- final def isIncompleteIn(base: Symbol): Boolean =
- this.isDeferred ||
- (this hasFlag ABSOVERRIDE) && {
- val supersym = superSymbol(base)
- supersym == NoSymbol || supersym.isIncompleteIn(base)
- }
-
- // Does not always work if the rawInfo is a SourcefileLoader, see comment
- // in "def coreClassesFirst" in Global.
- final def exists: Boolean =
- this != NoSymbol && (!owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType })
-
- final def isInitialized: Boolean =
- validTo != NoPeriod
-
- final def isStableClass: Boolean = {
- def hasNoAbstractTypeMember(clazz: Symbol): Boolean =
- (clazz hasFlag STABLE) || {
- var e = clazz.info.decls.elems
- while ((e ne null) && !(e.sym.isAbstractType && info.member(e.sym.name) == e.sym))
- e = e.next
- e == null
- }
- def checkStable() =
- (info.baseClasses forall hasNoAbstractTypeMember) && { setFlag(STABLE); true }
- isClass && (hasFlag(STABLE) || checkStable())
- }
-
-
- /** The variance of this symbol as an integer */
- final def variance: Int =
- if (isCovariant) 1
- else if (isContravariant) -1
- else 0
-
-// Flags, owner, and name attributes --------------------------------------------------------------
-
- def owner: Symbol = rawowner
- override final def owner_=(owner: Symbol) {
- if (originalOwner contains this) ()
- else originalOwner(this) = rawowner
-
- rawowner = owner
- }
- private[Symbols] def flattenName(): Name = {
- // TODO: this assertion causes me a lot of trouble in the interpeter in situations
- // where everything proceeds smoothly if there's no assert. I don't think calling "name"
- // on a symbol is the right place to throw fatal exceptions if things don't look right.
- // It really hampers exploration.
- assert(rawowner.isClass, "fatal: %s has non-class owner %s after flatten.".format(rawname + idString, rawowner))
- nme.flattenedName(rawowner.name, rawname)
- }
-
- def ownerChain: List[Symbol] = this :: owner.ownerChain
- def enclClassChain: List[Symbol] = {
- if (this eq NoSymbol) Nil
- else if (isClass && !isPackageClass) this :: owner.enclClassChain
- else owner.enclClassChain
- }
-
- def ownersIterator: Iterator[Symbol] = new Iterator[Symbol] {
- private var current = Symbol.this
- def hasNext = current ne NoSymbol
- def next = { val r = current; current = current.owner; r }
- }
-
- /** same as ownerChain contains sym, but more efficient, and
- * with a twist for refinement classes. A refinement class
- * has a transowner X if an of its parents has transowner X.
- */
- def hasTransOwner(sym: Symbol): Boolean = {
- var o = this
- while ((o ne sym) && (o ne NoSymbol)) o = o.owner
- (o eq sym) ||
- isRefinementClass && (info.parents exists (_.typeSymbol.hasTransOwner(sym)))
- }
-
- def name: Name = rawname
-
- final def name_=(name: Name) {
- if (name != rawname) {
- if (owner.isClass) {
- var ifs = owner.infos
- while (ifs != null) {
- ifs.info.decls.rehash(this, name)
- ifs = ifs.prev
- }
- }
- rawname = name
- }
- }
-
- /** If this symbol has an expanded name, its original name, otherwise its name itself.
- * @see expandName
- */
- def originalName = nme.originalName(name)
-
- final def flags: Long = {
- val fs = rawflags & phase.flagMask
- (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift)
- }
- override final def flags_=(fs: Long) = rawflags = fs
- final def setFlag(mask: Long): this.type = { rawflags = rawflags | mask; this }
- final def resetFlag(mask: Long): this.type = { rawflags = rawflags & ~mask; this }
- final def getFlag(mask: Long): Long = flags & mask
- final def resetFlags() { rawflags = rawflags & TopLevelCreationFlags }
-
- /** The class or term up to which this symbol is accessible,
- * or RootClass if it is public.
- */
- def accessBoundary(base: Symbol): Symbol = {
- if (hasFlag(PRIVATE) || isLocal) owner
- else if (hasAccessBoundary && !phase.erasedTypes) privateWithin
- else if (hasFlag(PROTECTED)) base
- else RootClass
- }
-
- def isLessAccessibleThan(other: Symbol): Boolean = {
- val tb = this.accessBoundary(owner)
- val ob1 = other.accessBoundary(owner)
- val ob2 = ob1.linkedClassOfClass
- var o = tb
- while (o != NoSymbol && o != ob1 && o != ob2) {
- o = o.owner
- }
- o != NoSymbol && o != tb
- }
-
-// Info and Type -------------------------------------------------------------------
-
- private[Symbols] var infos: TypeHistory = null
-
- /** Get type. The type of a symbol is:
- * for a type symbol, the type corresponding to the symbol itself,
- * @M you should use tpeHK for a type symbol with type parameters if
- * the kind of the type need not be *, as tpe introduces dummy arguments
- * to generate a type of kind *
- * for a term symbol, its usual type
- */
- override def tpe: Type = info
-
- /** Get type info associated with symbol at current phase, after
- * ensuring that symbol is initialized (i.e. type is completed).
- */
- override def info: Type = try {
- // Eugene: insert same thread assertion here
- var cnt = 0
- while (validTo == NoPeriod) {
- //if (settings.debug.value) System.out.println("completing " + this);//DEBUG
- assert(infos ne null, this.name)
- assert(infos.prev eq null, this.name)
- val tp = infos.info
- //if (settings.debug.value) System.out.println("completing " + this.rawname + tp.getClass());//debug
-
- if ((rawflags & LOCKED) != 0L) { // rolled out once for performance
- lock {
- setInfo(ErrorType)
- throw CyclicReference(this, tp)
- }
- } else {
- rawflags |= LOCKED
-// activeLocks += 1
- // lockedSyms += this
- }
- val current = phase
- try {
- phase = phaseOf(infos.validFrom)
- tp.complete(this)
- } finally {
- unlock()
- phase = current
- }
- cnt += 1
- // allow for two completions:
- // one: sourceCompleter to LazyType, two: LazyType to completed type
- if (cnt == 3) abort("no progress in completing " + this + ":" + tp)
- }
- val result = rawInfo
- result
- } catch {
- case ex: CyclicReference =>
- if (settings.debug.value) println("... trying to complete "+this)
- throw ex
- }
-
- override def info_=(info: Type) {
- assert(info ne null)
- infos = TypeHistory(currentPeriod, info, null)
- unlock()
- validTo = if (info.isComplete) currentPeriod else NoPeriod
- }
-
- /** Set initial info. */
- def setInfo(info: Type): this.type = { info_=(info); this }
-
- def setInfoOwnerAdjusted(info: Type): this.type = setInfo(info.atOwner(this))
-
- /** Set new info valid from start of this phase. */
- final def updateInfo(info: Type): Symbol = {
- assert(phaseId(infos.validFrom) <= phase.id)
- if (phaseId(infos.validFrom) == phase.id) infos = infos.prev
- infos = TypeHistory(currentPeriod, info, infos)
- validTo = if (info.isComplete) currentPeriod else NoPeriod
- this
- }
-
- def hasRawInfo: Boolean = infos ne null
-
- /** Return info without checking for initialization or completing */
- def rawInfo: Type = {
- var infos = this.infos
- assert(infos != null)
- val curPeriod = currentPeriod
- val curPid = phaseId(curPeriod)
-
- if (validTo != NoPeriod) {
- // skip any infos that concern later phases
- while (curPid < phaseId(infos.validFrom) && infos.prev != null)
- infos = infos.prev
-
- if (validTo < curPeriod) {
- // adapt any infos that come from previous runs
- val current = phase
- try {
- infos = adaptInfos(infos)
-
- //assert(runId(validTo) == currentRunId, name)
- //assert(runId(infos.validFrom) == currentRunId, name)
-
- if (validTo < curPeriod) {
- var itr = infoTransformers.nextFrom(phaseId(validTo))
- infoTransformers = itr; // caching optimization
- while (itr.pid != NoPhase.id && itr.pid < current.id) {
- phase = phaseWithId(itr.pid)
- val info1 = itr.transform(this, infos.info)
- if (info1 ne infos.info) {
- infos = TypeHistory(currentPeriod + 1, info1, infos)
- this.infos = infos
- }
- validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform
- itr = itr.next
- }
- validTo = if (itr.pid == NoPhase.id) curPeriod
- else period(currentRunId, itr.pid)
- }
- } finally {
- phase = current
- }
- }
- }
- infos.info
- }
-
- // adapt to new run in fsc.
- private def adaptInfos(infos: TypeHistory): TypeHistory =
- if (infos == null || runId(infos.validFrom) == currentRunId) {
- infos
- } else {
- val prev1 = adaptInfos(infos.prev)
- if (prev1 ne infos.prev) prev1
- else {
- def adaptToNewRun(info: Type): Type =
- if (isPackageClass) info else adaptToNewRunMap(info)
- val pid = phaseId(infos.validFrom)
- validTo = period(currentRunId, pid)
- phase = phaseWithId(pid)
- val info1 = adaptToNewRun(infos.info)
- if (info1 eq infos.info) {
- infos.validFrom = validTo
- infos
- } else {
- this.infos = TypeHistory(validTo, info1, prev1)
- this.infos
- }
- }
- }
-
- /** Initialize the symbol */
- final def initialize: this.type = {
- if (!isInitialized) info
- this
- }
-
- /** Was symbol's type updated during given phase? */
- final def isUpdatedAt(pid: Phase#Id): Boolean = {
- var infos = this.infos
- while ((infos ne null) && phaseId(infos.validFrom) != pid + 1) infos = infos.prev
- infos ne null
- }
-
- /** Was symbol's type updated during given phase? */
- final def hasTypeAt(pid: Phase#Id): Boolean = {
- var infos = this.infos
- while ((infos ne null) && phaseId(infos.validFrom) > pid) infos = infos.prev
- infos ne null
- }
-
- /** Modify term symbol's type so that a raw type C is converted to an existential C[_]
- *
- * This is done in checkAccessible and overriding checks in refchecks
- * We can't do this on class loading because it would result in infinite cycles.
- */
- final def cookJavaRawInfo() {
- if (hasFlag(TRIEDCOOKING)) return else setFlag(TRIEDCOOKING) // only try once...
- val oldInfo = info
- doCookJavaRawInfo()
- }
-
- protected def doCookJavaRawInfo(): Unit
-
-
- /** The type constructor of a symbol is:
- * For a type symbol, the type corresponding to the symbol itself,
- * excluding parameters.
- * Not applicable for term symbols.
- */
- def typeConstructor: Type =
- abort("typeConstructor inapplicable for " + this)
-
- /** @M -- tpe vs tpeHK:
- * Symbol::tpe creates a TypeRef that has dummy type arguments to get a type of kind *
- * Symbol::tpeHK creates a TypeRef without type arguments, but with type params --> higher-kinded if non-empty list of tpars
- * calling tpe may hide errors or introduce spurious ones
- * (e.g., when deriving a type from the symbol of a type argument that must be higher-kinded)
- * as far as I can tell, it only makes sense to call tpe in conjunction with a substitution that replaces the generated dummy type arguments by their actual types
- */
- def tpeHK = if (isType) typeConstructor else tpe // @M! used in memberType
-
- /** The type parameters of this symbol, without ensuring type completion.
- * assumption: if a type starts out as monomorphic, it will not acquire
- * type parameters later.
- */
- def unsafeTypeParams: List[Symbol] =
- if (isMonomorphicType) List()
- else {
- val current = phase
- try {
- while ((phase.prev ne NoPhase) && phase.prev.keepsTypeParams) phase = phase.prev
- if (phase ne current) phase = phase.next
- if (settings.debug.value && settings.verbose.value && (phase ne current))
- log("checking unsafeTypeParams(" + this + ") at: " + current + " reading at: " + phase)
- rawInfo.typeParams
- } finally {
- phase = current
- }
- }
-
- /** The type parameters of this symbol.
- * assumption: if a type starts out as monomorphic, it will not acquire
- * type parameters later.
- */
- def typeParams: List[Symbol] =
- if (isMonomorphicType)
- List()
- else {
- if (validTo == NoPeriod) {
- val current = phase
- try {
- phase = phaseOf(infos.validFrom)
- rawInfo.load(this)
- } finally {
- phase = current
- }
- }
- rawInfo.typeParams
- }
-
- /** The value parameter sections of this symbol.
- */
- def paramss: List[List[Symbol]] = info.paramss
- def hasParamWhich(cond: Symbol => Boolean) = paramss exists (_ exists cond)
-
- /** The least proper supertype of a class; includes all parent types
- * and refinement where needed. You need to compute that in a situation like this:
- * {
- * class C extends P { ... }
- * new C
- * }
- */
- def classBound: Type = {
- val tp = refinedType(info.parents, owner)
- val thistp = tp.typeSymbol.thisType
- val oldsymbuf = new ListBuffer[Symbol]
- val newsymbuf = new ListBuffer[Symbol]
- for (sym <- info.decls.toList) {
- // todo: what about public references to private symbols?
- if (sym.isPublic && !sym.isConstructor) {
- oldsymbuf += sym
- newsymbuf += (
- if (sym.isClass)
- tp.typeSymbol.newAbstractType(sym.pos, sym.name.toTypeName).setInfo(sym.existentialBound)
- else
- sym.cloneSymbol(tp.typeSymbol))
- }
- }
- val oldsyms = oldsymbuf.toList
- val newsyms = newsymbuf.toList
- for (sym <- newsyms) {
- addMember(thistp, tp, sym.setInfo(sym.info.substThis(this, thistp).substSym(oldsyms, newsyms)))
- }
- tp
- }
-
- /** If we quantify existentially over this symbol,
- * the bound of the type variable that stands for it
- * pre: symbol is a term, a class, or an abstract type (no alias type allowed)
- */
- def existentialBound: Type =
- if (this.isClass)
- polyType(this.typeParams, TypeBounds.upper(this.classBound))
- else if (this.isAbstractType)
- this.info
- else if (this.isTerm)
- TypeBounds.upper(intersectionType(List(this.tpe, SingletonClass.tpe)))
- else
- abort("unexpected alias type: "+this)
-
- /** Reset symbol to initial state
- */
- def reset(completer: Type) {
- resetFlags
- infos = null
- validTo = NoPeriod
- //limit = NoPhase.id
- setInfo(completer)
- }
-
- /**
- * Adds the interface scala.Serializable to the parents of a ClassInfoType.
- * Note that the tree also has to be updated accordingly.
- */
- def makeSerializable() {
- info match {
- case ci @ ClassInfoType(_, _, _) =>
- updateInfo(ci.copy(parents = ci.parents ::: List(SerializableClass.tpe)))
- case i =>
- abort("Only ClassInfoTypes can be made serializable: "+ i)
- }
- }
-
-// Comparisons ----------------------------------------------------------------
-
- /** A total ordering between symbols that refines the class
- * inheritance graph (i.e. subclass.isLess(superclass) always holds).
- * the ordering is given by: (_.isType, -_.baseTypeSeq.length) for type symbols, followed by `id'.
- */
- final def isLess(that: Symbol): Boolean = {
- def baseTypeSeqLength(sym: Symbol) =
- if (sym.isAbstractType) 1 + sym.info.bounds.hi.baseTypeSeq.length
- else sym.info.baseTypeSeq.length
- if (this.isType)
- (that.isType &&
- { val diff = baseTypeSeqLength(this) - baseTypeSeqLength(that)
- diff > 0 || diff == 0 && this.id < that.id })
- else
- that.isType || this.id < that.id
- }
-
- /** A partial ordering between symbols.
- * (this isNestedIn that) holds iff this symbol is defined within
- * a class or method defining that symbol
- */
- final def isNestedIn(that: Symbol): Boolean =
- owner == that || owner != NoSymbol && (owner isNestedIn that)
-
- /** Is this class symbol a subclass of that symbol? */
- final def isNonBottomSubClass(that: Symbol): Boolean =
- this == that || this.isError || that.isError ||
- info.baseTypeIndex(that) >= 0
-
- final def isSubClass(that: Symbol): Boolean = {
- isNonBottomSubClass(that) ||
- this == NothingClass ||
- this == NullClass &&
- (that == AnyClass ||
- that != NothingClass && (that isSubClass AnyRefClass))
- }
- final def isNumericSubClass(that: Symbol): Boolean =
- definitions.isNumericSubClass(this, that)
-
-// Overloaded Alternatives ---------------------------------------------------------
-
- def alternatives: List[Symbol] =
- if (hasFlag(OVERLOADED)) info.asInstanceOf[OverloadedType].alternatives
- else List(this)
-
- def filter(cond: Symbol => Boolean): Symbol =
- if (hasFlag(OVERLOADED)) {
- //assert(info.isInstanceOf[OverloadedType], "" + this + ":" + info);//DEBUG
- val alts = alternatives
- val alts1 = alts filter cond
- if (alts1 eq alts) this
- else if (alts1.isEmpty) NoSymbol
- else if (alts1.tail.isEmpty) alts1.head
- else owner.newOverloaded(info.prefix, alts1)
- } else if (this == NoSymbol || cond(this)) {
- this
- } else NoSymbol
-
- def suchThat(cond: Symbol => Boolean): Symbol = {
- val result = filter(cond)
- assert(!(result hasFlag OVERLOADED), result.alternatives)
- result
- }
-
-// Cloneing -------------------------------------------------------------------
-
- /** A clone of this symbol */
- final def cloneSymbol: Symbol =
- cloneSymbol(owner)
-
- /** A clone of this symbol, but with given owner */
- final def cloneSymbol(owner: Symbol): Symbol = {
- val newSym = cloneSymbolImpl(owner)
- newSym.privateWithin = privateWithin
- newSym.setInfo(info.cloneInfo(newSym))
- .setFlag(this.rawflags).setAnnotations(this.annotations)
- }
-
- /** Internal method to clone a symbol's implementation without flags or type
- */
- def cloneSymbolImpl(owner: Symbol): Symbol
-
-// Access to related symbols --------------------------------------------------
-
- /** The primary constructor of a class */
- def primaryConstructor: Symbol = {
- var c = info.decl(
- if (isTrait || isImplClass) nme.MIXIN_CONSTRUCTOR
- else nme.CONSTRUCTOR)
- c = if (c hasFlag OVERLOADED) c.alternatives.head else c
- //assert(c != NoSymbol)
- c
- }
-
- /** The self symbol of a class with explicit self type, or else the
- * symbol itself.
- */
- def thisSym: Symbol = this
-
- /** The type of `this' in a class, or else the type of the symbol itself. */
- def typeOfThis = thisSym.tpe
-
- /** If symbol is a class, the type <code>this.type</code> in this class,
- * otherwise <code>NoPrefix</code>.
- * We always have: thisType <:< typeOfThis
- */
- def thisType: Type = NoPrefix
-
- /** Return every accessor of a primary constructor parameter in this case class.
- * The scope declarations may be out of order because fields with less than private
- * access are first given a regular getter, then a new renamed getter which comes
- * later in the declaration list. For this reason we have to pinpoint the
- * right accessors by starting with the original fields (which will be in the right
- * order) and looking for getters with applicable names. The getters may have the
- * standard name "foo" or may have been renamed to "foo$\d+" in SyntheticMethods.
- * See ticket #1373.
- */
- final def caseFieldAccessors: List[Symbol] = {
- val allWithFlag = info.decls.toList filter (_.isCaseAccessor)
- val (accessors, fields) = allWithFlag partition (_.isMethod)
-
- def findAccessor(field: Symbol): Symbol = {
- // There is another renaming the field may have undergone, for instance as in
- // ticket #2175: case class Property[T](private var t: T), t becomes Property$$t.
- // So we use the original name everywhere.
- val getterName = nme.getterName(field.originalName)
-
- // Note this is done in two passes intentionally, to ensure we pick up the original
- // getter if present before looking for the renamed getter.
- def origGetter = accessors find (_.originalName == getterName)
- def renamedGetter = accessors find (_.originalName startsWith (getterName + "$"))
- val accessorName = origGetter orElse renamedGetter
-
- // This fails more gracefully rather than throw an Error as it used to because
- // as seen in #2625, we can reach this point with an already erroneous tree.
- accessorName getOrElse NoSymbol
- // throw new Error("Could not find case accessor for %s in %s".format(field, this))
- }
-
- fields map findAccessor
- }
-
- final def constrParamAccessors: List[Symbol] =
- info.decls.toList filter (sym => !sym.isMethod && sym.isParamAccessor)
-
- /** The symbol accessed by this accessor (getter or setter) function. */
- final def accessed: Symbol = accessed(owner.info)
-
- /** The symbol accessed by this accessor function, but with given owner type */
- final def accessed(ownerTp: Type): Symbol = {
- assert(hasAccessorFlag)
- ownerTp.decl(nme.getterToLocal(if (isSetter) nme.setterToGetter(name) else name))
- }
-
- /** The implementation class of a trait */
- final def implClass: Symbol = owner.info.decl(nme.implClassName(name))
-
- /** The class that is logically an outer class of given `clazz'.
- * This is the enclosing class, except for classes defined locally to constructors,
- * where it is the outer class of the enclosing class
- */
- final def outerClass: Symbol =
- if (owner.isClass) owner
- else if (isClassLocalToConstructor) owner.enclClass.outerClass
- else owner.outerClass
-
- /** For a paramaccessor: a superclass paramaccessor for which this symbol
- * is an alias, NoSymbol for all others
- */
- def alias: Symbol = NoSymbol
-
- /** For a lazy value, its lazy accessor. NoSymbol for all others */
- def lazyAccessor: Symbol = NoSymbol
-
- /** If this is a lazy value, the lazy accessor; otherwise this symbol. */
- def lazyAccessorOrSelf: Symbol = if (isLazy) lazyAccessor else this
-
- /** For an outer accessor: The class from which the outer originates.
- * For all other symbols: NoSymbol
- */
- def outerSource: Symbol = NoSymbol
-
- /** The superclass of this class */
- def superClass: Symbol = if (info.parents.isEmpty) NoSymbol else info.parents.head.typeSymbol
-
- /** The directly or indirectly inherited mixins of this class
- * except for mixin classes inherited by the superclass. Mixin classes appear
- * in linearization order.
- */
- def mixinClasses: List[Symbol] = {
- val sc = superClass
- ancestors takeWhile (sc ne)
- }
-
- /** All directly or indirectly inherited classes.
- */
- def ancestors: List[Symbol] = info.baseClasses drop 1
-
- /** The package class containing this symbol, or NoSymbol if there
- * is not one. */
- def enclosingPackageClass: Symbol =
- if (this == NoSymbol) this else {
- var packSym = this.owner
- while (packSym != NoSymbol && !packSym.isPackageClass)
- packSym = packSym.owner
- packSym
- }
-
- /** The package containing this symbol, or NoSymbol if there
- * is not one. */
- def enclosingPackage: Symbol = {
- val packSym = enclosingPackageClass
- if (packSym != NoSymbol) packSym.companionModule
- else packSym
- }
-
- /** Return the original enclosing method of this symbol. It should return
- * the same thing as enclMethod when called before lambda lift,
- * but it preserves the original nesting when called afterwards.
- */
- def originalEnclosingMethod: Symbol = {
- if (isMethod) this
- else {
- val owner = originalOwner.getOrElse(this, rawowner)
- if (isLocalDummy) owner.enclClass.primaryConstructor
- else owner.originalEnclosingMethod
- }
- }
-
- /** The method or class which logically encloses the current symbol.
- * If the symbol is defined in the initialization part of a template
- * this is the template's primary constructor, otherwise it is
- * the physically enclosing method or class.
- *
- * Example 1:
- *
- * def f() { val x = { def g() = ...; g() } }
- *
- * In this case the owner chain of `g' is `x', followed by `f' and
- * `g.logicallyEnclosingMember == f`.
- *
- * Example 2:
- *
- * class C {
- * def <init> = { ... }
- * val x = { def g() = ...; g() } }
- * }
- *
- * In this case the owner chain of `g' is `x', followed by `C' but
- * g.logicallyEnclosingMember is the primary constructor symbol `<init>'
- * (or, for traits: `$init') of `C'.
- *
- */
- def logicallyEnclosingMember: Symbol =
- if (isLocalDummy) enclClass.primaryConstructor
- else if (isMethod || isClass) this
- else owner.logicallyEnclosingMember
-
- /** The top-level class containing this symbol */
- def toplevelClass: Symbol =
- if (owner.isPackageClass) {
- if (isClass) this else moduleClass
- } else owner.toplevelClass
-
- /** Is this symbol defined in the same scope and compilation unit as `that' symbol?
- */
- def isCoDefinedWith(that: Symbol) = (
- (this.rawInfo ne NoType) &&
- (this.owner == that.owner) && {
- !this.owner.isPackageClass ||
- (this.sourceFile eq null) ||
- (that.sourceFile eq null) ||
- (this.sourceFile == that.sourceFile) || {
- // recognize companion object in separate file and fail, else compilation
- // appears to succeed but highly opaque errors come later: see bug #1286
- if (this.sourceFile.path != that.sourceFile.path)
- throw InvalidCompanions(this, that)
-
- false
- }
- }
- )
-
- /** The internal representation of classes and objects:
- *
- * class Foo is "the class" or sometimes "the plain class"
- * object Foo is "the module"
- * class Foo$ is "the module class" (invisible to the user: it implements object Foo)
- *
- * class Foo <
- * ^ ^ (2) \
- * | | | \
- * | (5) | (3)
- * | | | \
- * (1) v v \
- * object Foo (4)-> > class Foo$
- *
- * (1) companionClass
- * (2) companionModule
- * (3) linkedClassOfClass
- * (4) moduleClass
- * (5) companionSymbol
- */
-
- /** For a module or case factory: the class with the same name in the same package.
- * For all others: NoSymbol
- * Note: does not work for classes owned by methods, see Namers.companionClassOf
- *
- * object Foo . companionClass --> class Foo
- */
- final def companionClass: Symbol = {
- if (this != NoSymbol)
- flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this)
- else NoSymbol
- }
-
- /** A helper method that factors the common code used the discover a
- * companion module of a class. If a companion module exists, its symbol is
- * returned, otherwise, `NoSymbol` is returned. The method assumes that
- * `this` symbol has already been checked to be a class (using `isClass`).
- */
- private final def companionModule0: Symbol =
- flatOwnerInfo.decl(name.toTermName).suchThat(
- sym => sym.hasFlag(MODULE) && (sym isCoDefinedWith this) && !sym.isMethod)
-
- /** For a class: the module or case class factory with the same name in the same package.
- * For all others: NoSymbol
- * Note: does not work for modules owned by methods, see Namers.companionModuleOf
- *
- * class Foo . companionModule --> object Foo
- */
- final def companionModule: Symbol =
- if (isClass && !isRefinementClass) companionModule0
- else NoSymbol
-
- /** For a module: its linked class
- * For a plain class: its linked module or case factory.
- * Note: does not work for modules owned by methods, see Namers.companionSymbolOf
- *
- * class Foo <-- companionSymbol --> object Foo
- */
- final def companionSymbol: Symbol =
- if (isTerm) companionClass
- else if (isClass) companionModule0
- else NoSymbol
-
- /** For a module class: its linked class
- * For a plain class: the module class of its linked module.
- *
- * class Foo <-- linkedClassOfClass --> class Foo$
- */
- final def linkedClassOfClass: Symbol =
- if (isModuleClass) companionClass else companionModule.moduleClass
-
- /**
- * Returns the rawInfo of the owner. If the current phase has flat classes,
- * it first applies all pending type maps to this symbol.
- *
- * assume this is the ModuleSymbol for B in the following definition:
- * package p { class A { object B { val x = 1 } } }
- *
- * The owner after flatten is "package p" (see "def owner"). The flatten type map enters
- * symbol B in the decls of p. So to find a linked symbol ("object B" or "class B")
- * we need to apply flatten to B first. Fixes #2470.
- */
- private final def flatOwnerInfo: Type = {
- if (needsFlatClasses)
- info
- owner.rawInfo
- }
-
- /** If this symbol is an implementation class, its interface, otherwise the symbol itself
- * The method follows two strategies to determine the interface.
- * - during or after erasure, it takes the last parent of the implementation class
- * (which is always the interface, by convention)
- * - before erasure, it looks up the interface name in the scope of the owner of the class.
- * This only works for implementation classes owned by other classes or traits.
- */
- final def toInterface: Symbol =
- if (isImplClass) {
- val result =
- if (phase.next.erasedTypes) {
- assert(!tpe.parents.isEmpty, this)
- tpe.parents.last.typeSymbol
- } else {
- owner.info.decl(nme.interfaceName(name))
- }
- assert(result != NoSymbol, this)
- result
- } else this
-
- /** The module class corresponding to this module.
- */
- def moduleClass: Symbol = NoSymbol
-
- /** The non-private symbol whose type matches the type of this symbol
- * in in given class.
- *
- * @param ofclazz The class containing the symbol's definition
- * @param site The base type from which member types are computed
- */
- final def matchingSymbol(ofclazz: Symbol, site: Type): Symbol =
- ofclazz.info.nonPrivateDecl(name).filter(sym =>
- !sym.isTerm || (site.memberType(this) matches site.memberType(sym)))
-
- /** The non-private member of `site' whose type and name match the type of this symbol
- */
- final def matchingSymbol(site: Type, admit: Long = 0L): Symbol =
- site.nonPrivateMemberAdmitting(name, admit).filter(sym =>
- !sym.isTerm || (site.memberType(this) matches site.memberType(sym)))
-
- /** The symbol overridden by this symbol in given class `ofclazz'.
- * @pre 'ofclazz' is a base class of this symbol's owner.
- */
- final def overriddenSymbol(ofclazz: Symbol): Symbol =
- if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, owner.thisType)
-
- /** The symbol overriding this symbol in given subclass `ofclazz'
- * @pre: `ofclazz' is a subclass of this symbol's owner
- */
- final def overridingSymbol(ofclazz: Symbol): Symbol =
- if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, ofclazz.thisType)
-
- /** Returns all symbols overriden by this symbol
- */
- final def allOverriddenSymbols: List[Symbol] =
- if (!owner.isClass) Nil
- else owner.ancestors map overriddenSymbol filter (_ != NoSymbol)
-
- /** Returns all symbols overridden by this symbol, plus all matching symbols
- * defined in parents of the selftype
- */
- final def extendedOverriddenSymbols: List[Symbol] =
- if (!owner.isClass) Nil
- else owner.thisSym.ancestors map overriddenSymbol filter (_ != NoSymbol)
-
- /** The symbol accessed by a super in the definition of this symbol when
- * seen from class `base'. This symbol is always concrete.
- * pre: `this.owner' is in the base class sequence of `base'.
- */
- final def superSymbol(base: Symbol): Symbol = {
- var bcs = base.info.baseClasses.dropWhile(owner !=).tail
- var sym: Symbol = NoSymbol
- while (!bcs.isEmpty && sym == NoSymbol) {
- if (!bcs.head.isImplClass)
- sym = matchingSymbol(bcs.head, base.thisType).suchThat(!_.isDeferred)
- bcs = bcs.tail
- }
- sym
- }
-
- /** The getter of this value or setter definition in class `base', or NoSymbol if
- * none exists.
- */
- final def getter(base: Symbol): Symbol = {
- val getterName = if (isSetter) nme.setterToGetter(name) else nme.getterName(name)
- base.info.decl(getterName) filter (_.hasAccessorFlag)
- }
-
- /** The setter of this value or getter definition, or NoSymbol if none exists */
- final def setter(base: Symbol): Symbol = setter(base, false)
-
- final def setter(base: Symbol, hasExpandedName: Boolean): Symbol = {
- var sname = nme.getterToSetter(nme.getterName(name))
- if (hasExpandedName) sname = nme.expandedSetterName(sname, base)
- base.info.decl(sname) filter (_.hasAccessorFlag)
- }
-
- /** The case module corresponding to this case class
- * @pre case class is a member of some other class or package
- */
- final def caseModule: Symbol = {
- var modname = name.toTermName
- if (privateWithin.isClass && !privateWithin.isModuleClass && !hasFlag(EXPANDEDNAME))
- modname = nme.expandedName(modname, privateWithin)
- initialize.owner.info.decl(modname).suchThat(_.isModule)
- }
-
- /** If this symbol is a type parameter skolem (not an existential skolem!)
- * its corresponding type parameter, otherwise this */
- def deSkolemize: Symbol = this
-
- /** If this symbol is an existential skolem the location (a Tree or null)
- * where it was unpacked. Resulttype is AnyRef because trees are not visible here. */
- def unpackLocation: AnyRef = null
-
- /** Remove private modifier from symbol `sym's definition. If `sym' is a
- * term symbol rename it by expanding its name to avoid name clashes
- */
- final def makeNotPrivate(base: Symbol) {
- if (this hasFlag PRIVATE) {
- setFlag(notPRIVATE)
- if (isMethod && !isDeferred) setFlag(lateFINAL)
- if (!isStaticModule && !isClassConstructor) {
- expandName(base)
- if (isModule) moduleClass.makeNotPrivate(base)
- }
- }
- }
-
- /** change name by appending $$<fully-qualified-name-of-class `base'>
- * Do the same for any accessed symbols or setters/getters
- */
- def expandName(base: Symbol) {
- if (this.isTerm && this != NoSymbol && !hasFlag(EXPANDEDNAME)) {
- setFlag(EXPANDEDNAME)
- if (hasAccessorFlag && !isDeferred) {
- accessed.expandName(base)
- } else if (hasGetter) {
- getter(owner).expandName(base)
- setter(owner).expandName(base)
- }
- name = nme.expandedName(name, base)
- if (isType) name = name
- }
- }
-/* code for fixing nested objects
- def expandModuleClassName() {
- name = newTypeName(name.toString + "$")
- }
-
- def isExpandedModuleClass: Boolean = name(name.length - 1) == '$'
-*/
- def sourceFile: AbstractFile =
- if (isModule) moduleClass.sourceFile
- else toplevelClass.sourceFile
-
- def sourceFile_=(f: AbstractFile) {
- abort("sourceFile_= inapplicable for " + this)
- }
-
- /** If this is a sealed class, its known direct subclasses.
- * Otherwise, the empty set.
- */
- def children: Set[Symbol] = Set()
-
- /** Recursively assemble all children of this symbol.
- */
- def sealedDescendants: Set[Symbol] = children.flatMap(_.sealedDescendants) + this
-
-// ToString -------------------------------------------------------------------
-
- /** A tag which (in the ideal case) uniquely identifies class symbols */
- final def tag = fullName.##
-
- /** The simple name of this Symbol */
- final def simpleName: Name = name
-
- /** The String used to order otherwise identical sealed symbols.
- * This uses data which is stable across runs and variable classpaths
- * (the initial Name) before falling back on id, which varies depending
- * on exactly when a symbol is loaded.
- */
- final def sealedSortName = initName + "#" + id
-
- /** String representation of symbol's definition key word */
- final def keyString: String =
- if (isJavaInterface) "interface"
- else if (isTrait) "trait"
- else if (isClass) "class"
- else if (isType && !isParameter) "type"
- else if (isVariable) "var"
- else if (isPackage) "package"
- else if (isModule) "object"
- else if (isSourceMethod) "def"
- else if (isTerm && (!isParameter || isParamAccessor)) "val"
- else ""
-
- /** Accurate string representation of symbols' kind, suitable for developers. */
- final def accurateKindString: String =
- if (isPackage) "package"
- else if (isPackageClass) "package class"
- else if (isPackageObject) "package object"
- else if (isPackageObjectClass) "package object class"
- else if (isRefinementClass) "refinement class"
- else if (isModule) "module"
- else if (isModuleClass) "module class"
- else sanitizedKindString
-
- /** String representation of symbol's kind, suitable for the masses. */
- private def sanitizedKindString: String =
- if (isPackage || isPackageClass) "package"
- else if (isModule || isModuleClass) "object"
- else if (isAnonymousClass) "anonymous class"
- else if (isRefinementClass) ""
- else if (isTrait) "trait"
- else if (isClass) "class"
- else if (isType) "type"
- else if (isTerm && isLazy) "lazy value"
- else if (isVariable) "variable"
- else if (isClassConstructor) "constructor"
- else if (isSourceMethod) "method"
- else if (isTerm) "value"
- else ""
-
- final def kindString: String =
- if (settings.debug.value) accurateKindString
- else sanitizedKindString
-
- /** If the name of the symbol's owner should be used when you care about
- * seeing an interesting name: in such cases this symbol is e.g. a method
- * parameter with a synthetic name, a constructor named "this", an object
- * "package", etc. The kind string, if non-empty, will be phrased relative
- * to the name of the owner.
- */
- def hasMeaninglessName = (
- isSetterParameter // x$1
- || isClassConstructor // this
- || isPackageObject // package
- || isPackageObjectClass // package$
- || isRefinementClass // <refinement>
- )
-
- /** String representation of symbol's simple name.
- * If !settings.debug translates expansions of operators back to operator symbol.
- * E.g. $eq => =.
- * If settings.uniqid, adds id.
- */
- def nameString = decodedName + idString
-
- /** If settings.uniqid is set, the symbol's id, else "" */
- final def idString = if (settings.uniqid.value) "#"+id else ""
-
- /** String representation, including symbol's kind e.g., "class Foo", "method Bar".
- * If hasMeaninglessName is true, uses the owner's name to disambiguate identity.
- */
- override def toString = compose(
- kindString,
- if (hasMeaninglessName) owner.nameString else nameString
- )
-
- /** String representation of location.
- */
- def ownsString = {
- val owns = owner.skipPackageObject
- if (owns.isClass && !owns.printWithoutPrefix && !isScalaPackageClass) "" + owns
- else ""
- }
-
- /** String representation of location, plus a preposition. Doesn't do much,
- * for backward compatibility reasons.
- */
- def locationString = ownsString match {
- case "" => ""
- case s => " in " + s
- }
- def fullLocationString = toString + locationString
-
- /** String representation of symbol's definition following its name */
- final def infoString(tp: Type): String = {
- def typeParamsString: String = tp match {
- case PolyType(tparams, _) if tparams.nonEmpty =>
- (tparams map (_.defString)).mkString("[", ",", "]")
- case _ =>
- ""
- }
- if (isClass)
- typeParamsString + " extends " + tp.resultType
- else if (isAliasType)
- typeParamsString + " = " + tp.resultType
- else if (isAbstractType)
- typeParamsString + {
- tp.resultType match {
- case TypeBounds(lo, hi) =>
- (if (lo.typeSymbol == NothingClass) "" else " >: " + lo) +
- (if (hi.typeSymbol == AnyClass) "" else " <: " + hi)
- case rtp =>
- "<: " + rtp
- }
- }
- else if (isModule)
- moduleClass.infoString(tp)
- else
- tp match {
- case PolyType(tparams, res) =>
- typeParamsString + infoString(res)
- case NullaryMethodType(res) =>
- infoString(res)
- case MethodType(params, res) =>
- params.map(_.defString).mkString("(", ",", ")") + infoString(res)
- case _ =>
- ": " + tp
- }
- }
-
- def infosString = infos.toString()
-
- def hasFlagsToString(mask: Long): String = flagsToString(
- flags & mask,
- if (hasAccessBoundary) privateWithin.toString else ""
- )
-
- /** String representation of symbol's variance */
- def varianceString: String =
- if (variance == 1) "+"
- else if (variance == -1) "-"
- else ""
-
- def defaultFlagMask =
- if (settings.debug.value) -1L
- else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE
- else ExplicitFlags
-
- def defaultFlagString = hasFlagsToString(defaultFlagMask)
-
- /** String representation of symbol's definition */
- def defString = compose(
- defaultFlagString,
- keyString,
- varianceString + nameString + (
- if (hasRawInfo) infoString(rawInfo) else "<_>"
- )
- )
-
- /** Concatenate strings separated by spaces */
- private def compose(ss: String*) = ss filter (_ != "") mkString " "
-
- def isSingletonExistential =
- nme.isSingletonName(name) && (info.bounds.hi.typeSymbol isSubClass SingletonClass)
-
- /** String representation of existentially bound variable */
- def existentialToString =
- if (isSingletonExistential && !settings.debug.value)
- "val " + nme.dropSingletonName(name) + ": " + dropSingletonType(info.bounds.hi)
- else defString
- }
-
- /** A class for term symbols */
- class TermSymbol(initOwner: Symbol, initPos: Position, initName: TermName)
- extends Symbol(initOwner, initPos, initName) {
- final override def isTerm = true
-
- override def name: TermName = super.name
- privateWithin = NoSymbol
-
- var referenced: Symbol = NoSymbol
-
- def cloneSymbolImpl(owner: Symbol): Symbol =
- new TermSymbol(owner, pos, name).copyAttrsFrom(this)
-
- def copyAttrsFrom(original: TermSymbol): this.type = {
- referenced = original.referenced
- this
- }
-
- private val validAliasFlags = SUPERACCESSOR | PARAMACCESSOR | MIXEDIN | SPECIALIZED
-
- override def alias: Symbol =
- if (hasFlag(validAliasFlags)) initialize.referenced
- else NoSymbol
-
- def setAlias(alias: Symbol): TermSymbol = {
- assert(alias != NoSymbol, this)
- assert(!alias.isOverloaded, alias)
- assert(hasFlag(validAliasFlags), this)
-
- referenced = alias
- this
- }
-
- override def outerSource: Symbol =
- if (name endsWith nme.OUTER) initialize.referenced
- else NoSymbol
-
- override def moduleClass: Symbol =
- if (hasFlag(MODULE)) referenced else NoSymbol
-
- def setModuleClass(clazz: Symbol): TermSymbol = {
- assert(hasFlag(MODULE))
- referenced = clazz
- this
- }
-
- def setLazyAccessor(sym: Symbol): TermSymbol = {
- assert(isLazy && (referenced == NoSymbol || referenced == sym), this)
- referenced = sym
- this
- }
-
- override def lazyAccessor: Symbol = {
- assert(isLazy, this)
- referenced
- }
-
- protected def doCookJavaRawInfo() {
- def cook(sym: Symbol) {
- require(sym hasFlag JAVA)
- // @M: I think this is more desirable, but Martin prefers to leave raw-types as-is as much as possible
- // object rawToExistentialInJava extends TypeMap {
- // def apply(tp: Type): Type = tp match {
- // // any symbol that occurs in a java sig, not just java symbols
- // // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14
- // case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty =>
- // val eparams = typeParamsToExistentials(sym, sym.typeParams)
- // existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe)))
- // case _ =>
- // mapOver(tp)
- // }
- // }
- val tpe1 = rawToExistential(sym.tpe)
- // println("cooking: "+ sym +": "+ sym.tpe +" to "+ tpe1)
- if (tpe1 ne sym.tpe) {
- sym.setInfo(tpe1)
- }
- }
-
- if (isJavaDefined)
- cook(this)
- else if (hasFlag(OVERLOADED))
- for (sym2 <- alternatives)
- if (sym2 hasFlag JAVA)
- cook(sym2)
- }
- }
-
- /** A class for module symbols */
- class ModuleSymbol(initOwner: Symbol, initPos: Position, initName: TermName)
- extends TermSymbol(initOwner, initPos, initName) {
- private var flatname: TermName = null
- // This method could use a better name from someone clearer on what the condition expresses.
- private def isFlatAdjusted = !isMethod && needsFlatClasses
-
- override def owner: Symbol =
- if (isFlatAdjusted) rawowner.owner
- else rawowner
-
- override def name: TermName =
- if (isFlatAdjusted) {
- if (flatname == null)
- flatname = flattenName().toTermName
-
- flatname
- } else rawname
-
- override def cloneSymbolImpl(owner: Symbol): Symbol =
- new ModuleSymbol(owner, pos, name).copyAttrsFrom(this)
- }
-
- /** A class for method symbols */
- class MethodSymbol(initOwner: Symbol, initPos: Position, initName: TermName)
- extends TermSymbol(initOwner, initPos, initName) {
- private var mtpePeriod = NoPeriod
- private var mtpePre: Type = _
- private var mtpeResult: Type = _
- private var mtpeInfo: Type = _
-
- override def cloneSymbolImpl(owner: Symbol): Symbol =
- new MethodSymbol(owner, pos, name).copyAttrsFrom(this)
-
- def typeAsMemberOf(pre: Type): Type = {
- if (mtpePeriod == currentPeriod) {
- if ((mtpePre eq pre) && (mtpeInfo eq info)) return mtpeResult
- } else if (isValid(mtpePeriod)) {
- mtpePeriod = currentPeriod
- if ((mtpePre eq pre) && (mtpeInfo eq info)) return mtpeResult
- }
- val res = pre.computeMemberType(this)
- mtpePeriod = currentPeriod
- mtpePre = pre
- mtpeInfo = info
- mtpeResult = res
- res
- }
- }
-
- /** A class of type symbols. Alias and abstract types are direct instances
- * of this class. Classes are instances of a subclass.
- */
- class TypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
- extends Symbol(initOwner, initPos, initName) {
- privateWithin = NoSymbol
- private var tyconCache: Type = null
- private var tyconRunId = NoRunId
- private var tpeCache: Type = _
- private var tpePeriod = NoPeriod
-
- override def name: TypeName = super.name.asInstanceOf[TypeName]
- final override def isType = true
- override def isNonClassType = true
- override def isAbstractType = isDeferred
- override def isAliasType = !isDeferred
-
- private def newTypeRef(targs: List[Type]) = {
- val pre = if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType
- typeRef(pre, this, targs)
- }
-
- /** Let's say you have a type definition
- *
- * type T <: Number
- *
- * and tsym is the symbol corresponding to T. Then
- *
- * tsym.info = TypeBounds(Nothing, Number)
- * tsym.tpe = TypeRef(NoPrefix, T, List())
- */
- override def tpe: Type = {
- if (tpeCache eq NoType) throw CyclicReference(this, typeConstructor)
- if (tpePeriod != currentPeriod) {
- if (isValid(tpePeriod)) {
- tpePeriod = currentPeriod
- } else {
- if (isInitialized) tpePeriod = currentPeriod
- tpeCache = NoType
- val targs =
- if (phase.erasedTypes && this != ArrayClass) List()
- else unsafeTypeParams map (_.typeConstructor) //@M! use typeConstructor to generate dummy type arguments,
- // sym.tpe should not be called on a symbol that's supposed to be a higher-kinded type
- // memberType should be used instead, that's why it uses tpeHK and not tpe
- tpeCache = newTypeRef(targs)
- }
- }
- assert(tpeCache ne null/*, "" + this + " " + phase*/)//debug
- tpeCache
- }
-
- // needed for experimental code for early types as type parameters
- // def refreshType() { tpePeriod = NoPeriod }
-
- override def typeConstructor: Type = {
- if ((tyconCache eq null) || tyconRunId != currentRunId) {
- tyconCache = newTypeRef(Nil)
- tyconRunId = currentRunId
- }
- assert(tyconCache ne null)
- tyconCache
- }
-
- override def info_=(tp: Type) {
- tpePeriod = NoPeriod
- tyconCache = null
- super.info_=(tp)
- }
-
- override def reset(completer: Type) {
- super.reset(completer)
- tpePeriod = NoPeriod
- tyconRunId = NoRunId
- }
-
- /*** example:
- * public class Test3<T> {}
- * public class Test1<T extends Test3> {}
- * info for T in Test1 should be >: Nothing <: Test3[_]
- */
- protected def doCookJavaRawInfo() {
- // don't require isJavaDefined, since T in the above example does not have that flag
- val tpe1 = rawToExistential(info)
- // println("cooking type: "+ this +": "+ info +" to "+ tpe1)
- if (tpe1 ne info) {
- setInfo(tpe1)
- }
- }
-
- def cloneSymbolImpl(owner: Symbol): Symbol =
- new TypeSymbol(owner, pos, name) //.toTypeName)
-
- incCounter(typeSymbolCount)
- }
-
- /** A class for type parameters viewed from inside their scopes
- *
- * @param origin Can be either a tree, or a symbol, or null.
- * If skolem got created from newTypeSkolem (called in Namers), origin denotes
- * the type parameter from which the skolem was created. If it got created from
- * skolemizeExistential, origin is either null or a Tree. If it is a Tree, it indicates
- * where the skolem was introduced (this is important for knowing when to pack it
- * again into ab Existential). origin is `null' only in skolemizeExistentials called
- * from <:< or isAsSpecific, because here its value does not matter.
- * I elieve the following invariant holds:
- *
- * origin.isInstanceOf[Symbol] == !hasFlag(EXISTENTIAL)
- */
- class TypeSkolem(initOwner: Symbol, initPos: Position, initName: TypeName, origin: AnyRef)
- extends TypeSymbol(initOwner, initPos, initName) {
-
- /** The skolemization level in place when the skolem was constructed */
- val level = skolemizationLevel
-
- final override def isSkolem = true
-
- /** If typeskolem comes from a type parameter, that parameter, otherwise skolem itself */
- override def deSkolemize = origin match {
- case s: Symbol => s
- case _ => this
- }
-
- /** If type skolem comes from an existential, the tree where it was created */
- override def unpackLocation = origin
-
- override def typeParams = info.typeParams //@M! (not deSkolemize.typeParams!!), also can't leave superclass definition: use info, not rawInfo
-
- override def cloneSymbolImpl(owner: Symbol): Symbol =
- new TypeSkolem(owner, pos, name, origin)
-
- override def nameString: String =
- if (settings.debug.value) (super.nameString + "&" + level)
- else super.nameString
- }
-
-
- /** A class for class symbols */
- class ClassSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
- extends TypeSymbol(initOwner, initPos, initName) {
-
- private var source: AbstractFile = null
- private var thissym: Symbol = this
-
- final override def isClass = true
- final override def isNonClassType = false
- final override def isAbstractType = false
- final override def isAliasType = false
-
- override def sourceFile =
- if (owner.isPackageClass) source
- else super.sourceFile
- override def sourceFile_=(f: AbstractFile) { source = f }
-
- override def reset(completer: Type) {
- super.reset(completer)
- thissym = this
- }
-
- private var flatname: TypeName = null
-
- override def owner: Symbol =
- if (needsFlatClasses) rawowner.owner
- else rawowner
-
- override def name: TypeName =
- if (needsFlatClasses) {
- if (flatname == null)
- flatname = flattenName().toTypeName
- flatname
- }
- else rawname.asInstanceOf[TypeName]
-
- private var thisTypeCache: Type = _
- private var thisTypePeriod = NoPeriod
-
- private var typeOfThisCache: Type = _
- private var typeOfThisPeriod = NoPeriod
-
- /** the type this.type in this class */
- override def thisType: Type = {
- val period = thisTypePeriod
- if (period != currentPeriod) {
- thisTypePeriod = currentPeriod
- if (!isValid(period)) thisTypeCache = ThisType(this)
- }
- thisTypeCache
- }
-
- /** A symbol carrying the self type of the class as its type */
- override def thisSym: Symbol = thissym
-
- /** the self type of an object foo is foo.type, not class<foo>.this.type
- */
- override def typeOfThis: Type = {
- if (getFlag(MODULE | IMPLCLASS) == MODULE.toLong && owner != NoSymbol) {
- val period = typeOfThisPeriod
- if (period != currentPeriod) {
- typeOfThisPeriod = currentPeriod
- if (!isValid(period))
- typeOfThisCache = singleType(owner.thisType, sourceModule)
- }
- typeOfThisCache
- }
- else thissym.tpe
- }
-
- /** Sets the self type of the class */
- override def typeOfThis_=(tp: Type) {
- thissym = newThisSym(pos).setInfo(tp)
- }
-
- override def cloneSymbolImpl(owner: Symbol): Symbol = {
- val clone = new ClassSymbol(owner, pos, name)
- if (thisSym != this) {
- clone.typeOfThis = typeOfThis
- clone.thisSym.name = thisSym.name
- }
- clone
- }
-
- override def sourceModule =
- if (isModuleClass) companionModule else NoSymbol
-
- private var childSet: Set[Symbol] = Set()
- override def children = childSet
- override def addChild(sym: Symbol) { childSet = childSet + sym }
-
- incCounter(classSymbolCount)
- }
-
- /** A class for module class symbols
- * Note: Not all module classes are of this type; when unpickled, we get
- * plain class symbols!
- */
- class ModuleClassSymbol(owner: Symbol, pos: Position, name: TypeName)
- extends ClassSymbol(owner, pos, name) {
- private var module: Symbol = null
- def this(module: TermSymbol) = {
- this(module.owner, module.pos, module.name.toTypeName)
- setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL)
- sourceModule = module
- }
- override def sourceModule = module
- private var implicitMembersCacheValue: List[Symbol] = List()
- private var implicitMembersCacheKey: Type = NoType
- def implicitMembers: List[Symbol] = {
- val tp = info
- if (implicitMembersCacheKey ne tp) {
- implicitMembersCacheKey = tp
- implicitMembersCacheValue = tp.implicitMembers
- }
- implicitMembersCacheValue
- }
- override def sourceModule_=(module: Symbol) { this.module = module }
- }
-
- /** An object representing a missing symbol */
- object NoSymbol extends Symbol(null, NoPosition, nme.NO_NAME) {
- setInfo(NoType)
- privateWithin = this
- override def info_=(info: Type) {
- infos = TypeHistory(1, NoType, null)
- unlock()
- validTo = currentPeriod
- }
- override def defString: String = toString
- override def locationString: String = ""
- override def enclClass: Symbol = this
- override def toplevelClass: Symbol = this
- override def enclMethod: Symbol = this
- override def owner: Symbol = abort("no-symbol does not have owner")
- override def sourceFile: AbstractFile = null
- override def ownerChain: List[Symbol] = List()
- override def ownersIterator: Iterator[Symbol] = Iterator.empty
- override def alternatives: List[Symbol] = List()
- override def reset(completer: Type) {}
- override def info: Type = NoType
- override def rawInfo: Type = NoType
- protected def doCookJavaRawInfo() {}
- override def accessBoundary(base: Symbol): Symbol = RootClass
- def cloneSymbolImpl(owner: Symbol): Symbol = abort()
- override def originalEnclosingMethod = this
- }
-
- def cloneSymbols[T <: Symbol](syms: List[T]): List[T] = {
- val syms1 = syms map (_.cloneSymbol.asInstanceOf[T])
- for (sym1 <- syms1) sym1.setInfo(sym1.info.substSym(syms, syms1))
- syms1
- }
-
- def cloneSymbols[T <: Symbol](syms: List[T], owner: Symbol): List[T] = {
- val syms1 = syms map (_.cloneSymbol(owner).asInstanceOf[T])
- for (sym1 <- syms1) sym1.setInfo(sym1.info.substSym(syms, syms1))
- syms1
- }
-
- /** An exception for cyclic references of symbol definitions */
- case class CyclicReference(sym: Symbol, info: Type)
- extends TypeError("illegal cyclic reference involving " + sym) {
- // printStackTrace() // debug
- }
-
- case class InvalidCompanions(sym1: Symbol, sym2: Symbol)
- extends Throwable("Companions '" + sym1 + "' and '" + sym2 + "' must be defined in same file") {
- override def toString = getMessage
- }
-
- /** A class for type histories */
- private sealed case class TypeHistory(var validFrom: Period, info: Type, prev: TypeHistory) {
- assert((prev eq null) || phaseId(validFrom) > phaseId(prev.validFrom), this)
- assert(validFrom != NoPeriod)
- override def toString() =
- "TypeHistory(" + phaseOf(validFrom)+":"+runId(validFrom) + "," + info + "," + prev + ")"
- }
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/TypeDebugging.scala b/src/compiler/scala/tools/nsc/symtab/TypeDebugging.scala
index 62e812704b..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/TypeDebugging.scala
+++ b/src/compiler/scala/tools/nsc/symtab/TypeDebugging.scala
@@ -1,72 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package symtab
-
-trait TypeDebugging {
- self: SymbolTable =>
-
- import definitions._
-
- // @M toString that is safe during debugging (does not normalize, ...)
- object TypeDebugStrings {
- object str {
- def parentheses(xs: List[_]): String = xs.mkString("(", ", ", ")")
- def brackets(xs: List[_]): String = if (xs.isEmpty) "" else xs.mkString("[", ", ", "]")
- def tparams(tparams: List[Type]): String = brackets(tparams map debug)
- def parents(ps: List[Type]): String = (ps map debug).mkString(" with ")
- def refine(defs: Scope): String = defs.toList.mkString("{", " ;\n ", "}")
- }
-
- def dump(tp: Type): Unit = {
- println("** " + tp + " / " + tp.getClass + " **")
- import tp._
-
- println("typeSymbol = " + typeSymbol)
- println("termSymbol = " + termSymbol)
- println("widen = " + widen)
- println("deconst = " + deconst)
- println("typeOfThis = " + typeOfThis)
- println("bounds = " + bounds)
- println("parents = " + parents)
- println("prefixChain = " + prefixChain)
- println("typeConstructor = " + typeConstructor)
- println(" .. typeConstructor.typeParams = " + typeConstructor.typeParams)
- println(" .. _.variance = " + (typeConstructor.typeParams map (_.variance)))
- println("typeArgs = " + typeArgs)
- println("resultType = " + resultType)
- println("finalResultType = " + finalResultType)
- println("paramss = " + paramss)
- println("paramTypes = " + paramTypes)
- println("typeParams = " + typeParams)
- println("boundSyms = " + boundSyms)
- println("baseTypeSeq = " + baseTypeSeq)
- println("baseClasses = " + baseClasses)
- println("toLongString = " + toLongString)
- }
-
- private def debug(tp: Type): String = tp match {
- case TypeRef(pre, sym, args) => debug(pre) + "." + sym.nameString + str.tparams(args)
- case ThisType(sym) => sym.nameString + ".this"
- case SingleType(pre, sym) => debug(pre) +"."+ sym.nameString +".type"
- case RefinedType(parents, defs) => str.parents(parents) + str.refine(defs)
- case ClassInfoType(parents, defs, clazz) => "class "+ clazz.nameString + str.parents(parents) + str.refine(defs)
- case PolyType(tparams, result) => str.brackets(tparams) + " " + debug(result)
- case TypeBounds(lo, hi) => ">: "+ debug(lo) +" <: "+ debug(hi)
- case tv @ TypeVar(_, _) => tv.toString
- case ExistentialType(tparams, qtpe) => "forSome "+ str.brackets(tparams) + " " + debug(qtpe)
- case _ => tp.toString
- }
- def debugString(tp: Type) = debug(tp)
- }
- private def TDS = TypeDebugStrings
-
- def paramString(tp: Type) = TDS.str parentheses (tp.params map (_.defString))
- def typeParamsString(tp: Type) = TDS.str brackets (tp.typeParams map (_.defString))
- def typeArgsString(tp: Type) = TDS.str brackets (tp.typeArgs map (_.safeToString))
- def debugString(tp: Type) = TDS debugString tp
-}
-
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 80a48e55fc..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1,5674 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-
-import scala.collection.{ mutable, immutable }
-import scala.ref.WeakReference
-import mutable.ListBuffer
-import ast.TreeGen
-import util.{ Position, NoPosition }
-import util.Statistics._
-import Flags._
-import scala.util.control.ControlThrowable
-import scala.annotation.tailrec
-
-/* A standard type pattern match:
- case ErrorType =>
- // internal: error
- case WildcardType =>
- // internal: unknown
- case NoType =>
- case NoPrefix =>
- case ThisType(sym) =>
- // sym.this.type
- case SuperType(thistpe, supertpe) =>
- // super references
- case SingleType(pre, sym) =>
- // pre.sym.type
- case ConstantType(value) =>
- // Int(2)
- case TypeRef(pre, sym, args) =>
- // pre.sym[targs]
- // Outer.this.C would be represented as TypeRef(ThisType(Outer), C, List())
- case RefinedType(parents, defs) =>
- // parent1 with ... with parentn { defs }
- case ExistentialType(tparams, result) =>
- // result forSome { tparams }
- case AnnotatedType(annots, tp, selfsym) =>
- // tp @annots
-
- // the following are non-value types; you cannot write them down in Scala source.
-
- case TypeBounds(lo, hi) =>
- // >: lo <: hi
- case ClassInfoType(parents, defs, clazz) =>
- // same as RefinedType except as body of class
- case MethodType(paramtypes, result) =>
- // (paramtypes)result
- // For instance def m(): T is represented as MethodType(List(), T)
- case NullaryMethodType(result) => // eliminated by uncurry
- // an eval-by-name type
- // For instance def m: T is represented as NullaryMethodType(T)
- case PolyType(tparams, result) =>
- // [tparams]result where result is a (Nullary)MethodType or ClassInfoType
-
- // The remaining types are not used after phase `typer'.
- case OverloadedType(pre, tparams, alts) =>
- // all alternatives of an overloaded ident
- case AntiPolyType(pre, targs) =>
- // rarely used, disappears when combined with a PolyType
- case TypeVar(inst, constr) =>
- // a type variable
- // Replace occurrences of type parameters with type vars, where
- // inst is the instantiation and constr is a list of bounds.
- case DeBruijnIndex(level, index)
- // for dependent method types: a type referring to a method parameter.
- // Not presently used, it seems.
-*/
-
-trait Types extends reflect.generic.Types { self: SymbolTable =>
- import definitions._
-
- //statistics
- def uniqueTypeCount = if (uniques == null) 0 else uniques.size
-
- private var explainSwitch = false
- private final val emptySymbolSet = immutable.Set.empty[Symbol]
-
- private final val LogPendingSubTypesThreshold = 50
- private final val LogPendingBaseTypesThreshold = 50
- private final val LogVolatileThreshold = 50
-
- /** A don't care value for the depth parameter in lubs/glbs and related operations */
- private final val AnyDepth = -3
-
- /** Decrement depth unless it is a don't care */
- private final def decr(depth: Int) = if (depth == AnyDepth) AnyDepth else depth - 1
-
- private final val printLubs = false
-
- /** The current skolemization level, needed for the algorithms
- * in isSameType, isSubType that do constraint solving under a prefix
- */
- var skolemizationLevel = 0
-
- /** A log of type variable with their original constraints. Used in order
- * to undo constraints in the case of isSubType/isSameType failure.
- */
- object undoLog {
- private type UndoLog = List[(TypeVar, TypeConstraint)]
- private[nsc] var log: UndoLog = List()
-
- /** Undo all changes to constraints to type variables upto `limit'
- */
- private def undoTo(limit: UndoLog) {
- while ((log ne limit) && log.nonEmpty) {
- val (tv, constr) = log.head
- tv.constr = constr
- log = log.tail
- }
- }
-
- private[Types] def record(tv: TypeVar) = {
- log ::= (tv, tv.constr.cloneInternal)
- }
- private[nsc] def clear() {
- if (settings.debug.value)
- self.log("Clearing " + log.size + " entries from the undoLog.")
-
- log = Nil
- }
-
- // `block` should not affect constraints on typevars
- def undo[T](block: => T): T = {
- val before = log
-
- try block
- finally undoTo(before)
- }
-
- // if `block` evaluates to false, it should not affect constraints on typevars
- def undoUnless(block: => Boolean): Boolean = {
- val before = log
- var result = false
-
- try result = block
- finally if (!result) undoTo(before)
-
- result
- }
- }
-
- /** A map from lists to compound types that have the given list as parents.
- * This is used to avoid duplication in the computation of base type sequences and baseClasses.
- * It makes use of the fact that these two operations depend only on the parents,
- * not on the refinement.
- */
- val intersectionWitness = new mutable.WeakHashMap[List[Type], WeakReference[Type]]
-
- private object gen extends {
- val global : Types.this.type = Types.this
- } with TreeGen
-
- import gen._
-
- /** A proxy for a type (identified by field `underlying') that forwards most
- * operations to it (for exceptions, see WrappingProxy, which forwards even more operations).
- * every operation that is overridden for some kind of types should be forwarded.
- */
- trait SimpleTypeProxy extends Type {
- def underlying: Type
-
- // the following operations + those in RewrappingTypeProxy are all operations
- // in class Type that are overridden in some subclass
- // Important to keep this up-to-date when new operations are added!
- override def isTrivial = underlying.isTrivial
- override def isHigherKinded: Boolean = underlying.isHigherKinded
- override def typeConstructor: Type = underlying.typeConstructor
- override def isNotNull = underlying.isNotNull
- override def isError = underlying.isError
- override def isErroneous = underlying.isErroneous
- override def isStable: Boolean = underlying.isStable
- override def isVolatile = underlying.isVolatile
- override def finalResultType = underlying.finalResultType
- override def paramSectionCount = underlying.paramSectionCount
- override def paramss = underlying.paramss
- override def params = underlying.params
- override def paramTypes = underlying.paramTypes
- override def termSymbol = underlying.termSymbol
- override def termSymbolDirect = underlying.termSymbolDirect
- override def typeParams = underlying.typeParams
- override def boundSyms = underlying.boundSyms
- override def typeSymbol = underlying.typeSymbol
- override def typeSymbolDirect = underlying.typeSymbolDirect
- override def widen = underlying.widen
- override def typeOfThis = underlying.typeOfThis
- override def bounds = underlying.bounds
- override def parents = underlying.parents
- override def prefix = underlying.prefix
- override def decls = underlying.decls
- override def baseType(clazz: Symbol) = underlying.baseType(clazz)
- override def baseTypeSeq = underlying.baseTypeSeq
- override def baseTypeSeqDepth = underlying.baseTypeSeqDepth
- override def baseClasses = underlying.baseClasses
- }
-
- /** A proxy for a type (identified by field `underlying') that forwards most
- * operations to it. Every operation that is overridden for some kind of types is
- * forwarded here. Some operations are rewrapped again.
- */
- trait RewrappingTypeProxy extends SimpleTypeProxy {
- protected def maybeRewrap(newtp: Type) = if (newtp eq underlying) this else rewrap(newtp)
- protected def rewrap(newtp: Type): Type
-
- // the following are all operations in class Type that are overridden in some subclass
- // Important to keep this up-to-date when new operations are added!
- override def widen = maybeRewrap(underlying.widen)
- override def narrow = underlying.narrow
- override def deconst = maybeRewrap(underlying.deconst)
- override def resultType = maybeRewrap(underlying.resultType)
- override def resultType(actuals: List[Type]) = maybeRewrap(underlying.resultType(actuals))
- override def finalResultType = maybeRewrap(underlying.finalResultType)
- override def paramSectionCount = 0
- override def paramss: List[List[Symbol]] = List()
- override def params: List[Symbol] = List()
- override def paramTypes: List[Type] = List()
- override def typeArgs = underlying.typeArgs
- override def notNull = maybeRewrap(underlying.notNull)
- override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = underlying.instantiateTypeParams(formals, actuals)
- override def skolemizeExistential(owner: Symbol, origin: AnyRef) = underlying.skolemizeExistential(owner, origin)
- override def normalize = maybeRewrap(underlying.normalize)
- override def dealias = maybeRewrap(underlying.dealias)
- override def cloneInfo(owner: Symbol) = maybeRewrap(underlying.cloneInfo(owner))
- override def atOwner(owner: Symbol) = maybeRewrap(underlying.atOwner(owner))
- override def prefixString = underlying.prefixString
- override def isComplete = underlying.isComplete
- override def complete(sym: Symbol) = underlying.complete(sym)
- override def load(sym: Symbol) { underlying.load(sym) }
- override def withAnnotations(annots: List[AnnotationInfo]) = maybeRewrap(underlying.withAnnotations(annots))
- override def withoutAnnotations = maybeRewrap(underlying.withoutAnnotations)
- }
-
- /** The base class for all types */
- abstract class Type extends AbsType {
-
- /** Types for which asSeenFrom always is the identity, no matter what
- * prefix or owner.
- */
- def isTrivial: Boolean = false
-
- /** Is this type higher-kinded, i.e., is it a type constructor @M */
- def isHigherKinded: Boolean = false
-
- /** Does this type denote a stable reference (i.e. singleton type)? */
- def isStable: Boolean = false
-
- /** Is this type dangerous (i.e. it might contain conflicting
- * type information when empty, so that it can be constructed
- * so that type unsoundness results.) A dangerous type has an underlying
- * type of the form T_1 with T_n { decls }, where one of the
- * T_i (i > 1) is an abstract type.
- */
- def isVolatile: Boolean = false
-
- /** Is this type guaranteed not to have `null' as a value? */
- def isNotNull: Boolean = false
-
- /** Is this type a structural refinement type (it 'refines' members that have not been inherited) */
- def isStructuralRefinement: Boolean = false
-
- /** Does this type depend immediately on an enclosing method parameter?
- * i.e., is it a singleton type whose termSymbol refers to an argument of the symbol's owner (which is a method)
- */
- def isImmediatelyDependent: Boolean = false
-
- /** Does this depend on an enclosing method parameter? */
- def isDependent: Boolean = IsDependentCollector.collect(this)
-
- /** True for WildcardType or BoundedWildcardType */
- def isWildcard = false
-
- /** The term symbol associated with the type
- * Note that the symbol of the normalized type is returned (@see normalize)
- */
- def termSymbol: Symbol = NoSymbol
-
- /** The type symbol associated with the type
- * Note that the symbol of the normalized type is returned (@see normalize)
- */
- def typeSymbol: Symbol = NoSymbol
-
- /** The term symbol *directly* associated with the type
- */
- def termSymbolDirect: Symbol = termSymbol
-
- /** The type symbol *directly* associated with the type
- */
- def typeSymbolDirect: Symbol = typeSymbol
-
- /** The base type underlying a type proxy,
- * identity on all other types */
- def underlying: Type = this
-
- /** Widen from singleton type to its underlying non-singleton
- * base type by applying one or more `underlying' dereferences,
- * identity for all other types.
- *
- * class Outer { class C ; val x: C }
- * val o: Outer
- * <o.x.type>.widen = o.C
- */
- def widen: Type = this
-
- /** Map a constant type or not-null-type to its underlying base type,
- * identity for all other types.
- */
- def deconst: Type = this
-
- /** The type of `this' of a class type or reference type
- */
- def typeOfThis: Type = typeSymbol.typeOfThis
-
- /** Map to a singleton type which is a subtype of this type.
- * The fallback implemented here gives
- * T.narrow = T' forSome { type T' <: T with Singleton }
- * Overridden where we know more about where types come from.
- */
- def narrow: Type =
- if (phase.erasedTypes) this
- else commonOwner(this) freshExistential ".type" setInfo singletonBounds(this) tpe
-
- /** For a TypeBounds type, itself;
- * for a reference denoting an abstract type, its bounds,
- * for all other types, a TypeBounds type all of whose bounds are this type.
- */
- def bounds: TypeBounds = TypeBounds(this, this)
-
- /** For a class or intersection type, its parents.
- * For a TypeBounds type, the parents of its hi bound.
- * inherited by typerefs, singleton types, and refinement types,
- * The empty list for all other types */
- def parents: List[Type] = List()
-
- /** For a typeref or single-type, the prefix of the normalized type (@see normalize).
- * NoType for all other types. */
- def prefix: Type = NoType
-
- /** A chain of all typeref or singletype prefixes of this type, longest first.
- * (Only used from safeToString.)
- */
- def prefixChain: List[Type] = this match {
- case TypeRef(pre, _, _) => pre :: pre.prefixChain
- case SingleType(pre, _) => pre :: pre.prefixChain
- case _ => List()
- }
-
- /** This type, without its type arguments @M */
- def typeConstructor: Type = this
-
- /** For a typeref, its arguments. The empty list for all other types */
- def typeArgs: List[Type] = List()
-
- /** For a (nullary) method or poly type, its direct result type,
- * the type itself for all other types. */
- def resultType: Type = this
-
- def resultType(actuals: List[Type]) = this
-
- /** Only used for dependent method types. */
- def resultApprox: Type = if(settings.YdepMethTpes.value) ApproximateDependentMap(resultType) else resultType
-
- /** If this is a TypeRef `clazz`[`T`], return the argument `T`
- * otherwise return this type
- */
- def remove(clazz: Symbol): Type = this
-
- /** For a curried/nullary method or poly type its non-method result type,
- * the type itself for all other types */
- def finalResultType: Type = this
-
- /** For a method type, the number of its value parameter sections,
- * 0 for all other types */
- def paramSectionCount: Int = 0
-
- /** For a method or poly type, a list of its value parameter sections,
- * the empty list for all other types */
- def paramss: List[List[Symbol]] = List()
-
- /** For a method or poly type, its first value parameter section,
- * the empty list for all other types */
- def params: List[Symbol] = List()
-
- /** For a method or poly type, the types of its first value parameter section,
- * the empty list for all other types */
- def paramTypes: List[Type] = List()
-
- /** For a (potentially wrapped) poly type, its type parameters,
- * the empty list for all other types */
- def typeParams: List[Symbol] = List()
-
- /** For a (potentially wrapped) poly or existential type, its bound symbols,
- * the empty list for all other types */
- def boundSyms: immutable.Set[Symbol] = emptySymbolSet
-
- /** Mixin a NotNull trait unless type already has one
- * ...if the option is given, since it is causing typing bugs.
- */
- def notNull: Type =
- if (!settings.Ynotnull.value || isNotNull || phase.erasedTypes) this
- else NotNullType(this)
-
- /** Replace formal type parameter symbols with actual type arguments.
- *
- * Amounts to substitution except for higher-kinded types. (See overridden method in TypeRef) -- @M
- */
- def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type =
- if (sameLength(formals, actuals)) this.subst(formals, actuals) else ErrorType
-
- /** If this type is an existential, turn all existentially bound variables to type skolems.
- * @param owner The owner of the created type skolems
- * @param origin The tree whose type was an existential for which the skolem was created.
- */
- def skolemizeExistential(owner: Symbol, origin: AnyRef): Type = this
-
- /** A simple version of skolemizeExistential for situations where
- * owner or unpack location do not matter (typically used in subtype tests)
- */
- def skolemizeExistential: Type = skolemizeExistential(NoSymbol, null)
-
- /** Reduce to beta eta-long normal form.
- * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes.
- * Functions on types are also implemented as PolyTypes.
- *
- * Example: (in the below, <List> is the type constructor of List)
- * TypeRef(pre, <List>, List()) is replaced by
- * PolyType(X, TypeRef(pre, <List>, List(X)))
- */
- def normalize = this // @MAT
-
- /** Expands type aliases. */
- def dealias = this
-
- /** Is this type produced as a repair for an error? */
- def isError: Boolean = typeSymbol.isError || termSymbol.isError
-
- /** Is this type produced as a repair for an error? */
- def isErroneous: Boolean = ErroneousCollector.collect(this)
-
- /** Does this type denote a reference type which can be null? */
- // def isNullable: Boolean = false
-
- /** For a classtype or refined type, its defined or declared members;
- * inherited by subtypes and typerefs.
- * The empty scope for all other types.
- */
- def decls: Scope = EmptyScope
-
- /** The defined or declared members with name `name' in this type;
- * an OverloadedSymbol if several exist, NoSymbol if none exist.
- * Alternatives of overloaded symbol appear in the order they are declared.
- */
- def decl(name: Name): Symbol = findDecl(name, 0)
-
- /** The non-private defined or declared members with name `name' in this type;
- * an OverloadedSymbol if several exist, NoSymbol if none exist.
- * Alternatives of overloaded symbol appear in the order they are declared.
- */
- def nonPrivateDecl(name: Name): Symbol = findDecl(name, PRIVATE)
-
- /** A list of all members of this type (defined or inherited)
- * Members appear in linearization order of their owners.
- * Members with the same owner appear in reverse order of their declarations.
- */
- def members: List[Symbol] = findMember(nme.ANYNAME, 0, 0, false).alternatives
-
- /** A list of all non-private members of this type (defined or inherited) */
- def nonPrivateMembers: List[Symbol] =
- findMember(nme.ANYNAME, PRIVATE | BRIDGES, 0, false).alternatives
-
- /** A list of all non-private members of this type (defined or inherited),
- * admitting members with given flags `admit`
- */
- def nonPrivateMembersAdmitting(admit: Long): List[Symbol] =
- findMember(nme.ANYNAME, (PRIVATE | BRIDGES) & ~admit, 0, false).alternatives
-
- /** A list of all implicit symbols of this type (defined or inherited) */
- def implicitMembers: List[Symbol] =
- findMember(nme.ANYNAME, BRIDGES, IMPLICIT, false).alternatives
-
- /** A list of all deferred symbols of this type (defined or inherited) */
- def deferredMembers: List[Symbol] =
- findMember(nme.ANYNAME, BRIDGES, DEFERRED, false).alternatives
-
- /** The member with given name,
- * an OverloadedSymbol if several exist, NoSymbol if none exist */
- def member(name: Name): Symbol = findMember(name, BRIDGES, 0, false)
-
- /** The non-private member with given name,
- * an OverloadedSymbol if several exist, NoSymbol if none exist.
- * Bridges are excluded from the result
- */
- def nonPrivateMember(name: Name): Symbol =
- findMember(name, PRIVATE | BRIDGES, 0, false)
-
- /** The non-private member with given name, admitting members with given flags `admit`
- * an OverloadedSymbol if several exist, NoSymbol if none exist
- */
- def nonPrivateMemberAdmitting(name: Name, admit: Long): Symbol =
- findMember(name, (PRIVATE | BRIDGES) & ~admit, 0, false)
-
- /** The non-local member with given name,
- * an OverloadedSymbol if several exist, NoSymbol if none exist */
- def nonLocalMember(name: Name): Symbol =
- findMember(name, LOCAL | BRIDGES, 0, false)
-
- /** The least type instance of given class which is a supertype
- * of this type. Example:
- * class D[T]
- * class C extends p.D[Int]
- * ThisType(C).baseType(D) = p.D[Int]
- */
- def baseType(clazz: Symbol): Type = NoType
-
- /** This type as seen from prefix `pre' and class `clazz'. This means:
- * Replace all thistypes of `clazz' or one of its subclasses
- * by `pre' and instantiate all parameters by arguments of `pre'.
- * Proceed analogously for thistypes referring to outer classes.
- *
- * Example:
- * class D[T] { def m: T }
- * class C extends p.D[Int]
- * T.asSeenFrom(ThisType(C), D) (where D is owner of m)
- * = Int
- */
- def asSeenFrom(pre: Type, clazz: Symbol): Type =
- if (!isTrivial && (!phase.erasedTypes || pre.typeSymbol == ArrayClass)) {
- incCounter(asSeenFromCount)
- val start = startTimer(asSeenFromNanos)
- val m = new AsSeenFromMap(pre.normalize, clazz)
- val tp = m apply this
- val result = existentialAbstraction(m.capturedParams, tp)
- stopTimer(asSeenFromNanos, start)
- result
- } else this
-
- /** The info of `sym', seen as a member of this type.
- *
- * Example:
- * class D[T] { def m: T }
- * class C extends p.D[Int]
- * ThisType(C).memberType(m) = Int
- */
- def memberInfo(sym: Symbol): Type = {
- sym.info.asSeenFrom(this, sym.owner)
- }
-
- /** The type of `sym', seen as a member of this type. */
- def memberType(sym: Symbol): Type = sym match {
- case meth: MethodSymbol =>
- meth.typeAsMemberOf(this)
- case _ =>
- computeMemberType(sym)
- }
-
- def computeMemberType(sym: Symbol): Type = sym.tpeHK match { //@M don't prematurely instantiate higher-kinded types, they will be instantiated by transform, typedTypeApply, etc. when really necessary
- case OverloadedType(_, alts) =>
- OverloadedType(this, alts)
- case tp =>
- tp.asSeenFrom(this, sym.owner)
- }
-
- /** Substitute types `to' for occurrences of references to
- * symbols `from' in this type.
- */
- def subst(from: List[Symbol], to: List[Type]): Type =
- new SubstTypeMap(from, to) apply this
-
- /** Substitute symbols `to' for occurrences of symbols
- * `from' in this type.
- * !!! NOTE !!!: If you need to do a substThis and a substSym, the substThis has to come
- * first, as otherwise symbols will immediately get rebound in typeRef to the old
- * symbol.
- */
- def substSym(from: List[Symbol], to: List[Symbol]): Type =
- if (from eq to) this
- else new SubstSymMap(from, to) apply this
-
- /** Substitute all occurrences of `ThisType(from)' in this type
- * by `to'.
- * !!! NOTE !!!: If you need to do a substThis and a substSym, the substThis has to come
- * first, as otherwise symbols will immediately get rebound in typeRef to the old
- * symbol.
- */
- def substThis(from: Symbol, to: Type): Type =
- new SubstThisMap(from, to) apply this
-
- def substSuper(from: Type, to: Type): Type =
- new SubstSuperMap(from, to) apply this
-
- /** Returns all parts of this type which satisfy predicate `p' */
- def filter(p: Type => Boolean): List[Type] = new FilterTypeCollector(p).collect(this).toList
-
- /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p',
- * or None if none exists.
- */
- def find(p: Type => Boolean): Option[Type] = new FindTypeCollector(p).collect(this)
-
- /** Apply `f' to each part of this type */
- def foreach(f: Type => Unit) { new ForEachTypeTraverser(f).traverse(this) }
-
- /** Apply `f' to each part of this type; children get mapped before their parents */
- def map(f: Type => Type): Type = new TypeMap {
- def apply(x: Type) = f(mapOver(x))
- } apply this
-
- /** Is there part of this type which satisfies predicate `p'? */
- def exists(p: Type => Boolean): Boolean = !find(p).isEmpty
-
- /** Does this type contain a reference to this symbol? */
- def contains(sym: Symbol): Boolean = new ContainsCollector(sym).collect(this)
-
- /** Does this type contain a reference to this type */
- def containsTp(tp: Type): Boolean = new ContainsTypeCollector(tp).collect(this)
-
- /** Is this type a subtype of that type? */
- def <:<(that: Type): Boolean = {
- if (util.Statistics.enabled) stat_<:<(that)
- else {
- (this eq that) ||
- (if (explainSwitch) explain("<:", isSubType, this, that)
- else isSubType(this, that, AnyDepth))
- }
- }
-
- /** Can this type only be subtyped by bottom types?
- * This is assessed to be the case if the class is final,
- * and all type parameters (if any) are invariant.
- */
- def isFinalType = (
- typeSymbol.isFinal &&
- (typeSymbol.typeParams forall (_.variance == 0))
- )
-
- /** Is this type a subtype of that type in a pattern context?
- * Any type arguments on the right hand side are replaced with
- * fresh existentials, except for Arrays.
- *
- * See bug1434.scala for an example of code which would fail
- * if only a <:< test were applied.
- */
- def matchesPattern(that: Type): Boolean = {
- (this <:< that) || ((this, that) match {
- case (TypeRef(_, ArrayClass, List(arg1)), TypeRef(_, ArrayClass, List(arg2))) if arg2.typeSymbol.typeParams.nonEmpty =>
- arg1 matchesPattern arg2
- case (_, TypeRef(_, _, args)) =>
- val newtp = existentialAbstraction(args map (_.typeSymbol), that)
- !(that =:= newtp) && (this <:< newtp)
- case _ =>
- false
- })
- }
-
- def stat_<:<(that: Type): Boolean = {
- incCounter(subtypeCount)
- val start = startTimer(subtypeNanos)
- val result =
- (this eq that) ||
- (if (explainSwitch) explain("<:", isSubType, this, that)
- else isSubType(this, that, AnyDepth))
- stopTimer(subtypeNanos, start)
- result
- }
-
- /** Is this type a weak subtype of that type? True also for numeric types, i.e. Int weak_<:< Long.
- */
- def weak_<:<(that: Type): Boolean = {
- incCounter(subtypeCount)
- val start = startTimer(subtypeNanos)
- val result =
- ((this eq that) ||
- (if (explainSwitch) explain("weak_<:", isWeakSubType, this, that)
- else isWeakSubType(this, that)))
- stopTimer(subtypeNanos, start)
- result
- }
-
- /** Is this type equivalent to that type? */
- def =:=(that: Type): Boolean = (
- (this eq that) ||
- (if (explainSwitch) explain("=", isSameType, this, that)
- else isSameType(this, that))
- );
-
- /** Does this type implement symbol `sym' with same or stronger type?
- */
- def specializes(sym: Symbol): Boolean =
- if (explainSwitch) explain("specializes", specializesSym, this, sym)
- else specializesSym(this, sym)
-
- /** Is this type close enough to that type so that members
- * with the two type would override each other?
- * This means:
- * - Either both types are polytypes with the same number of
- * type parameters and their result types match after renaming
- * corresponding type parameters
- * - Or both types are (nullary) method types with equivalent type parameter types
- * and matching result types
- * - Or both types are equivalent
- * - Or phase.erasedTypes is false and both types are neither method nor
- * poly types.
- */
- def matches(that: Type): Boolean = matchesType(this, that, !phase.erasedTypes)
-
- /** Same as matches, except that non-method types are always assumed to match.
- */
- def looselyMatches(that: Type): Boolean = matchesType(this, that, true)
-
- /** The shortest sorted upwards closed array of types that contains
- * this type as first element.
- *
- * A list or array of types ts is upwards closed if
- *
- * for all t in ts:
- * for all typerefs p.s[args] such that t <: p.s[args]
- * there exists a typeref p'.s[args'] in ts such that
- * t <: p'.s['args] <: p.s[args],
- *
- * and
- *
- * for all singleton types p.s such that t <: p.s
- * there exists a singleton type p'.s in ts such that
- * t <: p'.s <: p.s
- *
- * Sorting is with respect to Symbol.isLess() on type symbols.
- */
- def baseTypeSeq: BaseTypeSeq = baseTypeSingletonSeq(this)
-
- /** The maximum depth (@see maxDepth)
- * of each type in the BaseTypeSeq of this type.
- */
- def baseTypeSeqDepth: Int = 1
-
- /** The list of all baseclasses of this type (including its own typeSymbol)
- * in reverse linearization order, starting with the class itself and ending
- * in class Any.
- */
- def baseClasses: List[Symbol] = List()
-
- /**
- * @param sym the class symbol
- * @return the index of given class symbol in the BaseTypeSeq of this type,
- * or -1 if no base type with given class symbol exists.
- */
- def baseTypeIndex(sym: Symbol): Int = {
- val bts = baseTypeSeq
- var lo = 0
- var hi = bts.length - 1
- while (lo <= hi) {
- val mid = (lo + hi) / 2
- val btssym = bts.typeSymbol(mid)
- if (sym == btssym) return mid
- else if (sym isLess btssym) hi = mid - 1
- else if (btssym isLess sym) lo = mid + 1
- else abort()
- }
- -1
- }
-
- /** If this is a poly- or methodtype, a copy with cloned type / value parameters
- * owned by `owner'. Identity for all other types.
- */
- def cloneInfo(owner: Symbol) = this
-
- /** Make sure this type is correct as the info of given owner; clone it if not.
- */
- def atOwner(owner: Symbol) = this
-
- protected def objectPrefix = "object "
- protected def packagePrefix = "package "
-
- def trimPrefix(str: String) = str stripPrefix objectPrefix stripPrefix packagePrefix
-
- /** The string representation of this type used as a prefix */
- def prefixString = trimPrefix(toString) + "#"
-
- /** The string representation of this type, with singletypes explained */
- def toLongString = {
- val str = toString
- if (str endsWith ".type") str + " (with underlying type " + widen + ")"
- else str
- }
-
- /** A test whether a type contains any unification type variables */
- def isGround: Boolean = this match {
- case TypeVar(_, constr) =>
- constr.instValid && constr.inst.isGround
- case TypeRef(pre, sym, args) =>
- sym.isPackageClass || pre.isGround && (args forall (_.isGround))
- case SingleType(pre, sym) =>
- sym.isPackageClass || pre.isGround
- case ThisType(_) | NoPrefix | WildcardType | NoType | ErrorType | ConstantType(_) =>
- true
- case _ =>
- typeVarToOriginMap(this) eq this
- }
-
- /** If this is a symbol loader type, load and assign a new type to
- * `sym'.
- */
- def load(sym: Symbol) {}
-
- private def findDecl(name: Name, excludedFlags: Int): Symbol = {
- var alts: List[Symbol] = List()
- var sym: Symbol = NoSymbol
- var e: ScopeEntry = decls.lookupEntry(name)
- while (e ne null) {
- if (!e.sym.hasFlag(excludedFlags)) {
- if (sym == NoSymbol) sym = e.sym
- else {
- if (alts.isEmpty) alts = List(sym)
- alts = e.sym :: alts
- }
- }
- e = decls.lookupNextEntry(e)
- }
- if (alts.isEmpty) sym
- else (baseClasses.head.newOverloaded(this, alts))
- }
-
- /**
- * Find member(s) in this type. If several members matching criteria are found, they are
- * returned in an OverloadedSymbol
- *
- * @param name The member's name, where nme.ANYNAME means `unspecified'
- * @param excludedFlags Returned members do not have these flags
- * @param requiredFlags Returned members do have these flags
- * @param stableOnly If set, return only members that are types or stable values
- */
- //TODO: use narrow only for modules? (correct? efficiency gain?)
- def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = {
- val suspension = TypeVar.Suspension
- // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
- // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
- // without this, the matchesType call would lead to type variables on both sides
- // of a subtyping/equality judgement, which can lead to recursive types being constructed.
- // See (t0851) for a situation where this happens.
- if (!this.isGround) {
- // PP: The foreach below was formerly expressed as:
- // for(tv @ TypeVar(_, _) <- this) { suspension suspend tv }
- //
- // The tree checker failed this saying a TypeVar is required, but a (Type @unchecked) was found.
- // This is a consequence of using a pattern match and variable binding + ticket #1503, which
- // was addressed by weakening the type of bindings in pattern matches if they occur on the right.
- // So I'm not quite sure why this works at all, as the checker is right that it is mistyped.
- // For now I modified it as below, which achieves the same without error.
- //
- // make each type var in this type use its original type for comparisons instead of collecting constraints
- this foreach {
- case tv: TypeVar => suspension suspend tv
- case _ => ()
- }
- }
-
- incCounter(findMemberCount)
- val start = startTimer(findMemberNanos)
-
- //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
- var members: Scope = null
- var member: Symbol = NoSymbol
- var excluded = excludedFlags | DEFERRED
- var continue = true
- var self: Type = null
- var membertpe: Type = null
- while (continue) {
- continue = false
- val bcs0 = baseClasses
- var bcs = bcs0
- while (!bcs.isEmpty) {
- val decls = bcs.head.info.decls
- var entry =
- if (name == nme.ANYNAME) decls.elems else decls.lookupEntry(name)
- while (entry ne null) {
- val sym = entry.sym
- if (sym hasAllFlags requiredFlags) {
- val excl = sym.getFlag(excluded)
- if (excl == 0L &&
- (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
- (bcs eq bcs0) ||
- !sym.isPrivateLocal ||
- (bcs0.head.hasTransOwner(bcs.head)))) {
- if (name.isTypeName || stableOnly && sym.isStable) {
- stopTimer(findMemberNanos, start)
- suspension.resumeAll
- return sym
- } else if (member == NoSymbol) {
- member = sym
- } else if (members eq null) {
- if (member.name != sym.name ||
- !(member == sym ||
- member.owner != sym.owner &&
- !sym.isPrivate && {
- if (self eq null) self = this.narrow
- if (membertpe eq null) membertpe = self.memberType(member)
- (membertpe matches self.memberType(sym))
- })) {
- members = new Scope(List(member, sym))
- }
- } else {
- var prevEntry = members.lookupEntry(sym.name)
- while ((prevEntry ne null) &&
- !(prevEntry.sym == sym ||
- prevEntry.sym.owner != sym.owner &&
- !sym.hasFlag(PRIVATE) && {
- if (self eq null) self = this.narrow
- self.memberType(prevEntry.sym) matches self.memberType(sym)
- })) {
- prevEntry = members lookupNextEntry prevEntry
- }
- if (prevEntry eq null) {
- members enter sym
- }
- }
- } else if (excl == DEFERRED.toLong) {
- continue = true
- }
- }
- entry = if (name == nme.ANYNAME) entry.next else decls lookupNextEntry entry
- } // while (entry ne null)
- // excluded = excluded | LOCAL
- bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
- } // while (!bcs.isEmpty)
- excluded = excludedFlags
- } // while (continue)
- stopTimer(findMemberNanos, start)
- suspension.resumeAll
- if (members eq null) {
- if (member == NoSymbol) incCounter(noMemberCount)
- member
- } else {
- incCounter(multMemberCount)
- baseClasses.head.newOverloaded(this, members.toList)
- }
- }
-
- /** The existential skolems and existentially quantified variables which are free in this type */
- def existentialSkolems: List[Symbol] = {
- var boundSyms: List[Symbol] = List()
- var skolems: List[Symbol] = List()
- for (t <- this) {
- t match {
- case ExistentialType(quantified, qtpe) =>
- boundSyms = boundSyms ::: quantified
- case TypeRef(_, sym, _) =>
- if ((sym hasFlag EXISTENTIAL) && !(boundSyms contains sym) && !(skolems contains sym))
- skolems = sym :: skolems
- case _ =>
- }
- }
- skolems
- }
-
- /** Return the annotations on this type. */
- def annotations: List[AnnotationInfo] = Nil
-
- /** Test for the presence of an annotation */
- def hasAnnotation(clazz: Symbol) = annotations exists { _.atp.typeSymbol == clazz }
-
- /** Add an annotation to this type */
- def withAnnotation(annot: AnnotationInfo) = withAnnotations(List(annot))
-
- /** Add a number of annotations to this type */
- def withAnnotations(annots: List[AnnotationInfo]): Type =
- annots match {
- case Nil => this
- case _ => AnnotatedType(annots, this, NoSymbol)
- }
-
- /** Remove any annotations from this type */
- def withoutAnnotations = this
-
- /** Remove any annotations from this type and from any
- * types embedded in this type. */
- def stripAnnotations = StripAnnotationsMap(this)
-
- /** Set the self symbol of an annotated type, or do nothing
- * otherwise. */
- def withSelfsym(sym: Symbol) = this
-
- /** The selfsym of an annotated type, or NoSymbol of anything else */
- def selfsym: Symbol = NoSymbol
-
- /** The kind of this type; used for debugging */
- def kind: String = "unknown type of class "+getClass()
- }
-
-// Subclasses ------------------------------------------------------------
-
- trait UniqueType {
- override lazy val hashCode: Int = super.hashCode()
- }
-
- /** A base class for types that defer some operations
- * to their immediate supertype.
- */
- abstract class SubType extends Type {
- def supertype: Type
- override def parents: List[Type] = supertype.parents
- override def decls: Scope = supertype.decls
- override def baseType(clazz: Symbol): Type = supertype.baseType(clazz)
- override def baseTypeSeq: BaseTypeSeq = supertype.baseTypeSeq
- override def baseTypeSeqDepth: Int = supertype.baseTypeSeqDepth
- override def baseClasses: List[Symbol] = supertype.baseClasses
- override def isNotNull = supertype.isNotNull
- }
-
- case class NotNullType(override val underlying: Type) extends SubType with RewrappingTypeProxy {
- def supertype = underlying
- protected def rewrap(newtp: Type): Type = NotNullType(newtp)
- override def isNotNull: Boolean = true
- override def notNull = this
- override def deconst: Type = underlying //todo: needed?
- override def safeToString: String = underlying.toString + " with NotNull"
- override def kind = "NotNullType"
- }
-
- /** A base class for types that represent a single value
- * (single-types and this-types).
- */
- abstract class SingletonType extends SubType with SimpleTypeProxy {
- def supertype = underlying
- override def isTrivial = false
- override def isStable = true
- override def isVolatile = underlying.isVolatile
- override def widen: Type = underlying.widen
- override def baseTypeSeq: BaseTypeSeq = {
- incCounter(singletonBaseTypeSeqCount)
- underlying.baseTypeSeq prepend this
- }
- override def isHigherKinded = false // singleton type classifies objects, thus must be kind *
- override def safeToString: String = prefixString + "type"
-/*
- override def typeOfThis: Type = typeSymbol.typeOfThis
- override def bounds: TypeBounds = TypeBounds(this, this)
- override def prefix: Type = NoType
- override def typeArgs: List[Type] = List()
- override def typeParams: List[Symbol] = List()
-*/
- }
-
- /** An object representing an erroneous type */
- case object ErrorType extends Type {
- // todo see whether we can do without
- override def isError: Boolean = true
- override def decls: Scope = new ErrorScope(NoSymbol)
- override def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = {
- var sym = decls lookup name
- if (sym == NoSymbol) {
- sym = NoSymbol.newErrorSymbol(name)
- decls enter sym
- }
- sym
- }
- override def baseType(clazz: Symbol): Type = this
- override def safeToString: String = "<error>"
- override def narrow: Type = this
- // override def isNullable: Boolean = true
- override def kind = "ErrorType"
- }
-
- /** An object representing an unknown type, used during type inference.
- * If you see WildcardType outside of inference it is almost certainly a bug.
- */
- case object WildcardType extends Type {
- override def isWildcard = true
- override def safeToString: String = "?"
- // override def isNullable: Boolean = true
- override def kind = "WildcardType"
- }
-
- case class BoundedWildcardType(override val bounds: TypeBounds) extends Type {
- override def isWildcard = true
- override def safeToString: String = "?" + bounds
- override def kind = "BoundedWildcardType"
- }
-
- /** An object representing a non-existing type */
- case object NoType extends Type {
- override def isTrivial: Boolean = true
- override def safeToString: String = "<notype>"
- // override def isNullable: Boolean = true
- override def kind = "NoType"
- }
-
- /** An object representing a non-existing prefix */
- case object NoPrefix extends Type {
- override def isTrivial: Boolean = true
- override def isStable: Boolean = true
- override def prefixString = ""
- override def safeToString: String = "<noprefix>"
- // override def isNullable: Boolean = true
- override def kind = "NoPrefixType"
- }
-
- /** A class for this-types of the form <sym>.this.type
- */
- abstract case class ThisType(sym: Symbol) extends SingletonType {
- //assert(sym.isClass && !sym.isModuleClass || sym.isRoot, sym)
- override def isTrivial: Boolean = sym.isPackageClass
- override def isNotNull = true
- override def typeSymbol = sym
- override def underlying: Type = sym.typeOfThis
- override def isVolatile = false
- override def isHigherKinded = sym.isRefinementClass && underlying.isHigherKinded
- override def prefixString =
- if (settings.debug.value) sym.nameString + ".this."
- else if (sym.isAnonOrRefinementClass) "this."
- else if (sym.printWithoutPrefix) ""
- else if (sym.isModuleClass) sym.fullName + "."
- else sym.nameString + ".this."
- override def safeToString: String =
- if (sym.isRoot) "<root>"
- else if (sym.isEmptyPackageClass) "<empty>"
- else super.safeToString
- override def narrow: Type = this
- override def kind = "ThisType"
- }
-
- object ThisType extends ThisTypeExtractor {
- def apply(sym: Symbol): Type =
- if (!phase.erasedTypes) unique(new ThisType(sym) with UniqueType)
- else if (sym.isImplClass) sym.typeOfThis
- else sym.tpe
- }
-
- /** A class for singleton types of the form <prefix>.<sym.name>.type.
- * Cannot be created directly; one should always use
- * `singleType' for creation.
- */
- case class SingleType(pre: Type, sym: Symbol) extends SingletonType {
- override val isTrivial: Boolean = pre.isTrivial
- // override def isNullable = underlying.isNullable
- override def isNotNull = underlying.isNotNull
- private var underlyingCache: Type = NoType
- private var underlyingPeriod = NoPeriod
- override def underlying: Type = {
- val period = underlyingPeriod
- if (period != currentPeriod) {
- underlyingPeriod = currentPeriod
- if (!isValid(period)) {
- underlyingCache = pre.memberType(sym).resultType;
- assert(underlyingCache ne this, this)
- }
- }
- underlyingCache
- }
-
- // more precise conceptually, but causes cyclic errors: (paramss exists (_ contains sym))
- override def isImmediatelyDependent = (sym ne NoSymbol) && (sym.owner.isMethod && sym.isValueParameter)
-
- override def isVolatile : Boolean = underlying.isVolatile && !sym.isStable
-/*
- override def narrow: Type = {
- if (phase.erasedTypes) this
- else {
- val thissym = refinedType(List(this), sym.owner, EmptyScope).typeSymbol
- if (sym.owner != NoSymbol) {
- //Console.println("narrowing module " + sym + thissym.owner);
- thissym.typeOfThis = this
- }
- thissym.thisType
- }
- }
-*/
- override def narrow: Type = this
-
- override def termSymbol = sym
- override def prefix: Type = pre
- override def prefixString: String =
- if ((sym.isEmptyPackage || sym.isInterpreterWrapper || sym.isPredefModule || sym.isScalaPackage) && !settings.debug.value) ""
- else pre.prefixString + sym.nameString + "."
- override def kind = "SingleType"
- }
-
- object SingleType extends SingleTypeExtractor
-
- abstract case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType {
- override val isTrivial: Boolean = thistpe.isTrivial && supertpe.isTrivial
- override def isNotNull = true;
- override def typeSymbol = thistpe.typeSymbol
- override def underlying = supertpe
- override def prefix: Type = supertpe.prefix
- override def prefixString = thistpe.prefixString.replaceAll("""this\.$""", "super.")
- override def narrow: Type = thistpe.narrow
- override def kind = "SuperType"
- }
-
- object SuperType extends SuperTypeExtractor {
- def apply(thistp: Type, supertp: Type): Type =
- if (phase.erasedTypes) supertp
- else unique(new SuperType(thistp, supertp) with UniqueType)
- }
-
- /** A class for the bounds of abstract types and type parameters
- */
- abstract case class TypeBounds(lo: Type, hi: Type) extends SubType {
- def supertype = hi
- override val isTrivial: Boolean = lo.isTrivial && hi.isTrivial
- override def bounds: TypeBounds = this
- def containsType(that: Type) = that match {
- case TypeBounds(_, _) => that <:< this
- case _ => lo <:< that && that <:< hi
- }
- // override def isNullable: Boolean = NullClass.tpe <:< lo;
- override def safeToString = ">: " + lo + " <: " + hi
- override def kind = "TypeBoundsType"
- }
-
- object TypeBounds extends TypeBoundsExtractor {
- def empty: TypeBounds = apply(NothingClass.tpe, AnyClass.tpe)
- def upper(hi: Type): TypeBounds = apply(NothingClass.tpe, hi)
- def lower(lo: Type): TypeBounds = apply(lo, AnyClass.tpe)
-
- def apply(lo: Type, hi: Type): TypeBounds =
- unique(new TypeBounds(lo, hi) with UniqueType)
- }
-
- /** A common base class for intersection types and class types
- */
- abstract class CompoundType extends Type {
-
- var baseTypeSeqCache: BaseTypeSeq = _
- private var baseTypeSeqPeriod = NoPeriod
- private var baseClassesCache: List[Symbol] = _
- private var baseClassesPeriod = NoPeriod
-
- override def baseTypeSeq: BaseTypeSeq = {
- val period = baseTypeSeqPeriod;
- if (period != currentPeriod) { // no caching in IDE
- baseTypeSeqPeriod = currentPeriod
- if (!isValidForBaseClasses(period)) {
- if (parents.exists(_.exists(_.isInstanceOf[TypeVar]))) {
- // rename type vars to fresh type params, take base type sequence of
- // resulting type, and rename back all the entries in that sequence
- var tvs = Set[TypeVar]()
- for (p <- parents)
- for (t <- p) t match {
- case tv: TypeVar => tvs += tv
- case _ =>
- }
- val varToParamMap: Map[Type, Symbol] = tvs map (tv => tv -> tv.origin.typeSymbol.cloneSymbol) toMap
- val paramToVarMap = varToParamMap map (_.swap)
- val varToParam = new TypeMap {
- def apply(tp: Type) = varToParamMap get tp match {
- case Some(sym) => sym.tpe
- case _ => mapOver(tp)
- }
- }
- val paramToVar = new TypeMap {
- def apply(tp: Type) = tp match {
- case TypeRef(_, tsym, _) if paramToVarMap.isDefinedAt(tsym) => paramToVarMap(tsym)
- case _ => mapOver(tp)
- }
- }
- val bts = copyRefinedType(this.asInstanceOf[RefinedType], parents map varToParam, varToParam mapOver decls).baseTypeSeq
- baseTypeSeqCache = bts lateMap paramToVar
- } else {
- incCounter(compoundBaseTypeSeqCount)
- baseTypeSeqCache = undetBaseTypeSeq
- baseTypeSeqCache = if (typeSymbol.isRefinementClass)
- memo(compoundBaseTypeSeq(this))(_.baseTypeSeq updateHead typeSymbol.tpe)
- else
- compoundBaseTypeSeq(this)
- // [Martin] suppressing memo-ization solves the problem with "same type after erasure" errors
- // when compiling with
- // scalac scala.collection.IterableViewLike.scala scala.collection.IterableLike.scala
- // I have not yet figured out precisely why this is the case.
- // My current assumption is that taking memos forces baseTypeSeqs to be computed
- // at stale types (i.e. the underlying typeSymbol has already another type).
- // I do not yet see precisely why this would cause a problem, but it looks
- // fishy in any case.
- }
- }
- //Console.println("baseTypeSeq(" + typeSymbol + ") = " + baseTypeSeqCache.toList);//DEBUG
- }
- if (baseTypeSeqCache eq undetBaseTypeSeq)
- throw new TypeError("illegal cyclic inheritance involving " + typeSymbol)
- baseTypeSeqCache
- }
-
- override def baseTypeSeqDepth: Int = baseTypeSeq.maxDepth
-
- override def baseClasses: List[Symbol] = {
- def computeBaseClasses: List[Symbol] =
- if (parents.isEmpty) List(typeSymbol)
- else {
- //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG
- // optimized, since this seems to be performance critical
- val superclazz = parents.head
- var mixins = parents.tail
- val sbcs = superclazz.baseClasses
- var bcs = sbcs
- def isNew(clazz: Symbol): Boolean = (
- superclazz.baseTypeIndex(clazz) < 0 &&
- { var p = bcs;
- while ((p ne sbcs) && (p.head != clazz)) p = p.tail;
- p eq sbcs
- }
- );
- while (!mixins.isEmpty) {
- def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] =
- if (mbcs.isEmpty) bcs
- else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail)
- else addMixinBaseClasses(mbcs.tail);
- bcs = addMixinBaseClasses(mixins.head.baseClasses)
- mixins = mixins.tail
- }
- typeSymbol :: bcs
- }
- val period = baseClassesPeriod
- if (period != currentPeriod) {
- baseClassesPeriod = currentPeriod
- if (!isValidForBaseClasses(period)) {
- baseClassesCache = null
- baseClassesCache = memo(computeBaseClasses)(typeSymbol :: _.baseClasses.tail)
- }
- }
- if (baseClassesCache eq null)
- throw new TypeError("illegal cyclic reference involving " + typeSymbol)
- baseClassesCache
- }
-
- /** The slightly less idiomatic use of Options is due to
- * performance considerations. A version using for comprehensions
- * might be too slow (this is deemed a hotspot of the type checker).
- *
- * See with Martin before changing this method.
- */
- def memo[A](op1: => A)(op2: Type => A): A = {
- def updateCache(): A = {
- intersectionWitness(parents) = new WeakReference(this)
- op1
- }
-
- intersectionWitness get parents match {
- case Some(ref) =>
- ref.get match {
- case Some(w) => if (w eq this) op1 else op2(w)
- case None => updateCache()
- }
- case None => updateCache()
- }
-
- }
-
- override def baseType(sym: Symbol): Type = {
- val index = baseTypeIndex(sym)
- if (index >= 0) baseTypeSeq(index) else NoType
- }
-
- override def narrow: Type = typeSymbol.thisType
- override def isNotNull: Boolean = parents exists (_.isNotNull)
-
- override def isStructuralRefinement: Boolean =
- typeSymbol.isAnonOrRefinementClass &&
- (decls.toList exists { entry => !entry.isConstructor && entry.allOverriddenSymbols.isEmpty })
-
- // override def isNullable: Boolean =
- // parents forall (p => p.isNullable && !p.typeSymbol.isAbstractType);
-
- override def safeToString: String =
- parents.mkString(" with ") +
- (if (settings.debug.value || parents.isEmpty || (decls.elems ne null))
- decls.mkString("{", "; ", "}") else "")
- }
-
- /** A class representing intersection types with refinements of the form
- * `<parents_0> with ... with <parents_n> { decls }'
- * Cannot be created directly;
- * one should always use `refinedType' for creation.
- */
- case class RefinedType(override val parents: List[Type],
- override val decls: Scope) extends CompoundType {
-
- override def isHigherKinded = (
- parents.nonEmpty &&
- (parents forall (_.isHigherKinded)) &&
- !phase.erasedTypes // @MO to AM: please check this class!
- )
-
- override def typeParams =
- if (isHigherKinded) parents.head.typeParams
- else super.typeParams
-
- //@M may result in an invalid type (references to higher-order args become dangling )
- override def typeConstructor =
- copyRefinedType(this, parents map (_.typeConstructor), decls)
-
- private def dummyArgs = typeParams map (_.typeConstructor)
-
- /* MO to AM: This is probably not correct
- * If they are several higher-kinded parents with different bounds we need
- * to take the intersection of their bounds
- */
- override def normalize = {
- if (isHigherKinded) {
- typeFun(
- typeParams,
- RefinedType(
- parents map {
- case TypeRef(pre, sym, List()) => TypeRef(pre, sym, dummyArgs)
- case p => p
- },
- decls,
- typeSymbol))
- }
- else super.normalize
- }
-
- /** A refined type P1 with ... with Pn { decls } is volatile if
- * one of the parent types Pi is an abstract type, and
- * either i > 1, or decls or a following parent Pj, j > 1, contributes
- * an abstract member.
- * A type contributes an abstract member if it has an abstract member which
- * is also a member of the whole refined type. A scope `decls' contributes
- * an abstract member if it has an abstract definition which is also
- * a member of the whole type.
- */
- override def isVolatile = {
- def isVisible(m: Symbol) =
- this.nonPrivateMember(m.name).alternatives contains m
- def contributesAbstractMembers(p: Type) =
- p.deferredMembers exists isVisible
-
- ((parents exists (_.isVolatile))
- ||
- (parents dropWhile (! _.typeSymbol.isAbstractType) match {
- case ps @ (_ :: ps1) =>
- (ps ne parents) ||
- (ps1 exists contributesAbstractMembers) ||
- (decls.iterator exists (m => m.isDeferred && isVisible(m)))
- case _ =>
- false
- }))
- }
-
- override def kind = "RefinedType"
- }
-
- object RefinedType extends RefinedTypeExtractor {
- def apply(parents: List[Type], decls: Scope, clazz: Symbol) =
- new RefinedType(parents, decls) { override def typeSymbol = clazz }
- }
-
- /** A class representing a class info
- */
- case class ClassInfoType(
- override val parents: List[Type],
- override val decls: Scope,
- override val typeSymbol: Symbol) extends CompoundType
- {
-
- /** refs indices */
- private final val NonExpansive = 0
- private final val Expansive = 1
-
- /** initialization states */
- private final val UnInitialized = 0
- private final val Initializing = 1
- private final val Initialized = 2
-
- private type RefMap = Map[Symbol, immutable.Set[Symbol]]
-
- /** All type parameters reachable from given type parameter
- * by a path which contains at least one expansive reference.
- * @See Kennedy, Pierce: On Decidability of Nominal Subtyping with Variance
- */
- def expansiveRefs(tparam: Symbol) = {
- if (state == UnInitialized) {
- computeRefs()
- while (state != Initialized) propagate()
- }
- getRefs(Expansive, tparam)
- }
-
- /* The rest of this class is auxiliary code for `expansiveRefs'
- */
-
- /** The type parameters which are referenced type parameters of this class.
- * Two entries: refs(0): Non-expansive references
- * refs(1): Expansive references
- */
- private var refs: Array[RefMap] = _
-
- /** The initialization state of the class: UnInialized --> Initializing --> Initialized
- */
- private var state = UnInitialized
-
- /** Get references for given type parameter
- * @param which in {NonExpansive, Expansive}
- * @param from The type parameter from which references originate.
- */
- private def getRefs(which: Int, from: Symbol): Set[Symbol] = refs(which) get from match {
- case Some(set) => set
- case none => Set()
- }
-
- /** Augment existing refs map with reference <pre>from -> to</pre>
- * @param which <- {NonExpansive, Expansive}
- */
- private def addRef(which: Int, from: Symbol, to: Symbol) {
- refs(which) = refs(which) + (from -> (getRefs(which, from) + to))
- }
-
- /** Augment existing refs map with references <pre>from -> sym</pre>, for
- * all elements <pre>sym</pre> of set `to'.
- * @param which <- {NonExpansive, Expansive}
- */
- private def addRefs(which: Int, from: Symbol, to: Set[Symbol]) {
- refs(which) = refs(which) + (from -> (getRefs(which, from) ++ to))
- }
-
- /** The ClassInfoType which belongs to the class containing given type parameter
- */
- private def classInfo(tparam: Symbol): ClassInfoType =
- tparam.owner.info.resultType match {
- case ci: ClassInfoType => ci
- case _ => classInfo(ObjectClass) // something's wrong; fall back to safe value
- // (this can happen only for erroneous programs).
- }
-
- /** Compute initial (one-step) references and set state to `Initializing'.
- */
- private def computeRefs() {
- refs = Array(Map(), Map())
- for (tparam <- typeSymbol.typeParams) {
- val enterRefs = new TypeMap {
- def apply(tp: Type): Type = {
- tp match {
- case TypeRef(_, sym, args) =>
- for ((tparam1, arg) <- sym.info.typeParams zip args)
- if (arg contains tparam) {
- addRef(NonExpansive, tparam, tparam1)
- if (arg.typeSymbol != tparam) addRef(Expansive, tparam, tparam1)
- }
- case _ =>
- }
- mapOver(tp)
- }
- }
- for (p <- parents) enterRefs(p)
- }
- state = Initializing
- }
-
- /** Propagate to form transitive closure.
- * Set state to Initialized if no change resulted from propagation.
- * @return true iff there as a change in last iteration
- */
- private def propagate(): Boolean = {
- if (state == UnInitialized) computeRefs()
- //Console.println("Propagate "+symbol+", initial expansive = "+refs(Expansive)+", nonexpansive = "+refs(NonExpansive))//DEBUG
- val lastRefs = Array(refs(0), refs(1))
- state = Initialized
- var change = false
- for ((from, targets) <- refs(NonExpansive).iterator)
- for (target <- targets) {
- var thatInfo = classInfo(target)
- if (thatInfo.state != Initialized)
- change = change | thatInfo.propagate()
- addRefs(NonExpansive, from, thatInfo.getRefs(NonExpansive, target))
- addRefs(Expansive, from, thatInfo.getRefs(Expansive, target))
- }
- for ((from, targets) <- refs(Expansive).iterator)
- for (target <- targets) {
- var thatInfo = classInfo(target)
- if (thatInfo.state != Initialized)
- change = change | thatInfo.propagate()
- addRefs(Expansive, from, thatInfo.getRefs(NonExpansive, target))
- }
- change = change || refs(0) != lastRefs(0) || refs(1) != lastRefs(1)
- if (change) state = Initializing
- //else Console.println("Propagate "+symbol+", final expansive = "+refs(Expansive)+", nonexpansive = "+refs(NonExpansive))//DEBUG
- change
- }
-
- // override def isNullable: Boolean =
- // symbol == AnyClass ||
- // symbol != NothingClass && (symbol isSubClass ObjectClass) && !(symbol isSubClass NonNullClass);
-
- // override def isNonNull: Boolean = symbol == NonNullClass || super.isNonNull;
- override def kind = "ClassInfoType"
- }
-
- object ClassInfoType extends ClassInfoTypeExtractor
-
- class PackageClassInfoType(decls: Scope, clazz: Symbol)
- extends ClassInfoType(List(), decls, clazz)
-
- /** A class representing a constant type.
- *
- * @param value ...
- */
- abstract case class ConstantType(value: Constant) extends SingletonType {
- override def underlying: Type = value.tpe
- assert(underlying.typeSymbol != UnitClass)
- override def isTrivial: Boolean = true
- override def isNotNull = value.value != null
- override def deconst: Type = underlying
- override def safeToString: String =
- underlying.toString + "(" + value.escapedStringValue + ")"
- // override def isNullable: Boolean = value.value eq null
- // override def isNonNull: Boolean = value.value ne null
- override def kind = "ConstantType"
- }
-
- object ConstantType extends ConstantTypeExtractor {
- def apply(value: Constant): ConstantType = {
- class UniqueConstantType extends ConstantType(value) with UniqueType {
- /** Save the type of 'value'. For Java enums, it depends on finding the linked class,
- * which might not be found after 'flatten'. */
- private lazy val _tpe: Type = value.tpe
- override def underlying: Type = _tpe
- }
- unique(new UniqueConstantType)
- }
- }
-
- private var volatileRecursions: Int = 0
- private val pendingVolatiles = new mutable.HashSet[Symbol]
-
- /** A class for named types of the form
- * `<prefix>.<sym.name>[args]'
- * Cannot be created directly; one should always use `typeRef'
- * for creation. (@M: Otherwise hashing breaks)
- *
- * @M: a higher-kinded type is represented as a TypeRef with sym.info.typeParams.nonEmpty, but args.isEmpty
- * @param pre ...
- * @param sym ...
- * @param args ...
- */
- abstract case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type {
-// assert(!sym.isAbstractType || pre.isStable || pre.isError)
-// assert(!pre.isInstanceOf[ClassInfoType], this)
-// assert(!(sym hasFlag (PARAM | EXISTENTIAL)) || pre == NoPrefix, this)
-// assert(args.isEmpty || !sym.info.typeParams.isEmpty, this)
-// assert(args.isEmpty || ((sym ne AnyClass) && (sym ne NothingClass))
-
- private val parentsCache = new ListOfTypesCache {
- @inline final def calculate() = thisInfo.parents map transform
- }
- private var baseTypeSeqCache: BaseTypeSeq = _
- private var baseTypeSeqPeriod = NoPeriod
-
- override def isStable: Boolean = {
- sym == NothingClass ||
- sym == SingletonClass ||
- sym.isAliasType && normalize.isStable ||
- sym.isAbstractType && (bounds.hi.typeSymbol isSubClass SingletonClass)
- }
-
- override def isVolatile: Boolean = {
- sym.isAliasType && normalize.isVolatile ||
- sym.isAbstractType && {
- // need to be careful not to fall into an infinite recursion here
- // because volatile checking is done before all cycles are detected.
- // the case to avoid is an abstract type directly or
- // indirectly upper-bounded by itself. See #2918
- try {
- volatileRecursions += 1
- if (volatileRecursions < LogVolatileThreshold)
- bounds.hi.isVolatile
- else if (pendingVolatiles(sym))
- true // we can return true here, because a cycle will be detected
- // here afterwards and an error will result anyway.
- else
- try {
- pendingVolatiles += sym
- bounds.hi.isVolatile
- } finally {
- pendingVolatiles -= sym
- }
- } finally {
- volatileRecursions -= 1
- }
- }
- }
-
- override lazy val isTrivial: Boolean =
- !sym.isTypeParameter && pre.isTrivial && args.forall(_.isTrivial)
-
- override def isNotNull =
- sym.isModuleClass || sym == NothingClass || isValueClass(sym) || super.isNotNull
-
- // @M: propagate actual type params (args) to `tp', by replacing formal type parameters with actual ones
- // if tp is higher kinded, the "actual" type arguments are types that simply reference the corresponding type parameters (unbound type variables)
- def transform(tp: Type): Type = {
- val res = tp.asSeenFrom(pre, sym.owner)
- if (sym.typeParams.isEmpty || (args exists (_.isError)) || isRaw(sym, args)/*#2266/2305*/) res
- else res.instantiateTypeParams(sym.typeParams, typeArgsOrDummies)
- }
-
- //@M! use appliedType on the polytype that represents the bounds (or if aliastype, the rhs)
- def transformInfo(tp: Type): Type = appliedType(tp.asSeenFrom(pre, sym.owner), typeArgsOrDummies)
-
- def thisInfo =
- if (sym.isAliasType) normalize
- else if (sym.isNonClassType) transformInfo(sym.info)
- else sym.info
-
- def relativeInfo = if (sym.isNonClassType) transformInfo(pre.memberInfo(sym)) else pre.memberInfo(sym)
-
- override def typeSymbol = if (sym.isAliasType) normalize.typeSymbol else sym
- override def termSymbol = if (sym.isAliasType) normalize.termSymbol else super.termSymbol
- override def typeSymbolDirect = sym
- override def termSymbolDirect = super.termSymbol
-
-/* @MAT
-whenever you see `tp.typeSymbol.isXXXX' and then act on tp based on that predicate, you're on thin ice,
-as `typeSymbol' (and `prefix') automatically normalize, but the other inspectors don't.
-In other words, even if `tp.normalize.sym.isXXX' is true, `tp.sym.isXXX' may be false (if sym were a public method to access the non-normalized typeSymbol)...
-
-In retrospect, I think `tp.typeSymbol.isXXX' or (worse) `tp.typeSymbol==XXX' should be replaced by `val tp = tp0.asXXX'.
-A type's typeSymbol should never be inspected directly.
-*/
-
- override def bounds: TypeBounds =
- if (sym.isAbstractType) thisInfo.bounds // transform(thisInfo.bounds).asInstanceOf[TypeBounds] // ??? seems to be doing asSeenFrom twice
- else super.bounds
-
- override def parents: List[Type] = parentsCache.get()
- override def typeOfThis = transform(sym.typeOfThis)
-
-/*
- override def narrow =
- if (sym.isModuleClass) transform(sym.thisType)
- else if (sym.isAliasType) normalize.narrow
- else super.narrow
-*/
- override def narrow =
- if (sym.isModuleClass) singleType(pre, sym.sourceModule)
- else if (sym.isAliasType) normalize.narrow
- else super.narrow
-
- override def prefix: Type =
- if (sym.isAliasType) normalize.prefix
- else pre
-
- override def typeArgs: List[Type] = args
- private def typeArgsOrDummies = if (!isHigherKinded) args else dummyArgs
-
- // @MAT was typeSymbol.unsafeTypeParams, but typeSymbol normalizes now
- private def typeParamsDirect =
- if (isDefinitionsInitialized) sym.typeParams
- else sym.unsafeTypeParams
-
- // placeholders derived from type params
- private def dummyArgs = typeParamsDirect map (_.typeConstructor) //@M must be .typeConstructor
-
- // (!result.isEmpty) IFF isHigherKinded
- override def typeParams: List[Symbol] = if (isHigherKinded) typeParamsDirect else List()
-
- override def typeConstructor = TypeRef(pre, sym, Nil)
- // note: does not go through typeRef. There's no need to because neither `pre' nor `sym' changes.
- // And there's a performance advantage to call TypeRef directly.
-
-
- // a reference (in a Scala program) to a type that has type parameters, but where the reference does not include type arguments
- // note that it doesn't matter whether the symbol refers to a java or scala symbol,
- // it does matter whether it occurs in java or scala code
- // typerefs w/o type params that occur in java signatures/code are considered raw types, and are represented as existential types
- override def isHigherKinded = args.isEmpty && typeParamsDirect.nonEmpty
-
- override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type =
- if (isHigherKinded) {
- val substTps = formals.intersect(typeParams)
-
- if (sameLength(substTps, typeParams))
- typeRef(pre, sym, actuals)
- else if (sameLength(formals, actuals)) // partial application (needed in infer when bunching type arguments from classes and methods together)
- typeRef(pre, sym, dummyArgs).subst(formals, actuals)
- else ErrorType
- }
- else
- super.instantiateTypeParams(formals, actuals)
-
-
- private var normalized: Type = null
-
- @inline private def betaReduce: Type = {
- assert(sameLength(sym.info.typeParams, typeArgs), this)
- // isHKSubType0 introduces synthetic type params so that betaReduce can first apply sym.info to typeArgs before calling asSeenFrom
- // asSeenFrom then skips synthetic type params, which are used to reduce HO subtyping to first-order subtyping, but which can't be instantiated from the given prefix and class
- // appliedType(sym.info, typeArgs).asSeenFrom(pre, sym.owner) // this crashes pos/depmet_implicit_tpbetareduce.scala
- transform(sym.info.resultType)
- }
-
- // @M: initialize (by sym.info call) needed (see test/files/pos/ticket0137.scala)
- @inline private def etaExpand: Type = {
- val tpars = sym.info.typeParams // must go through sym.info for typeParams to initialise symbol
- typeFunAnon(tpars, typeRef(pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
- }
-
- override def dealias: Type =
- if (sym.isAliasType && sameLength(sym.info.typeParams, args)) {
- betaReduce.dealias
- } else this
-
- def normalize0: Type =
- if (pre eq WildcardType) WildcardType // arises when argument-dependent types are approximated (see def depoly in implicits)
- else if (isHigherKinded) etaExpand // eta-expand, subtyping relies on eta-expansion of higher-kinded types
- else if (sym.isAliasType && sameLength(sym.info.typeParams, args))
- betaReduce.normalize // beta-reduce, but don't do partial application -- cycles have been checked in typeRef
- else if (sym.isRefinementClass)
- sym.info.normalize // I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers
- else {
- if(sym.isAliasType) ErrorType //println("!!error: "+(pre, sym, sym.info, sym.info.typeParams, args))
- else super.normalize
- }
-
- // TODO: test case that is compiled in a specific order and in different runs
- override def normalize: Type = {
- if (phase.erasedTypes) normalize0
- else {
- if (normalized == null)
- normalized = normalize0
-
- normalized
- }
- }
-
- override def decls: Scope = {
- sym.info match {
- case TypeRef(_, sym1, _) =>
- assert(sym1 != sym, this) // @MAT was != typeSymbol
- case _ =>
- }
- thisInfo.decls
- }
-
- override def baseType(clazz: Symbol): Type =
- if (sym == clazz) this
- else if (sym.isClass) transform(sym.info.baseType(clazz))
- else
- try {
- basetypeRecursions += 1
- if (basetypeRecursions < LogPendingBaseTypesThreshold)
- relativeInfo.baseType(clazz)
- else if (pendingBaseTypes contains this)
- if (clazz == AnyClass) clazz.tpe else NoType
- else
- try {
- pendingBaseTypes += this
- relativeInfo.baseType(clazz)
- } finally {
- pendingBaseTypes -= this
- }
- } finally {
- basetypeRecursions -= 1
- }
-
- override def baseTypeSeq: BaseTypeSeq = {
- val period = baseTypeSeqPeriod
- if (period != currentPeriod) {
- baseTypeSeqPeriod = currentPeriod
- if (!isValidForBaseClasses(period)) {
- incCounter(typerefBaseTypeSeqCount)
- baseTypeSeqCache = undetBaseTypeSeq
- baseTypeSeqCache =
- if (sym.isAbstractType) transform(bounds.hi).baseTypeSeq prepend this
- else sym.info.baseTypeSeq map transform
- }
- }
- if (baseTypeSeqCache == undetBaseTypeSeq)
- throw new TypeError("illegal cyclic inheritance involving " + sym)
- baseTypeSeqCache
- }
-
- override def baseTypeSeqDepth: Int = baseTypeSeq.maxDepth
-
- override def baseClasses: List[Symbol] = thisInfo.baseClasses
-
- // override def isNullable: Boolean = sym.info.isNullable
-
- override def safeToString: String = {
- if (!settings.debug.value) {
- this match {
- case TypeRef(_, RepeatedParamClass, arg :: _) => return arg + "*"
- case TypeRef(_, ByNameParamClass, arg :: _) => return "=> " + arg
- case _ =>
- if (isFunctionType(this))
- return normalize.typeArgs.init.mkString("(", ", ", ")") + " => " + normalize.typeArgs.last
- else if (isTupleTypeOrSubtype(this))
- return normalize.typeArgs.mkString("(", ", ", if (hasLength(normalize.typeArgs, 1)) ",)" else ")")
- else if (sym.isAliasType && prefixChain.exists(_.termSymbol.isSynthetic)) {
- val normed = normalize;
- if (normed ne this) return normed.toString
- }
- }
- }
- val monopart =
- if (!settings.debug.value &&
- (shorthands contains sym.fullName) &&
- (sym.ownerChain forall (_.isClass))) // ensure that symbol is not a local copy with a name coincidence
- sym.name.toString
- else
- pre.prefixString + sym.nameString
-
- var str = monopart + (if (args.isEmpty) "" else args.mkString("[", ",", "]"))
- if (sym.isPackageClass)
- packagePrefix + str
- else if (sym.isModuleClass)
- objectPrefix + str
- else if (sym.isAnonymousClass && sym.isInitialized && !settings.debug.value && !phase.erasedTypes)
- thisInfo.parents.mkString(" with ") + {
- if (sym.isStructuralRefinement)
- ((decls.toList filter { entry =>
- !entry.isConstructor && entry.allOverriddenSymbols.isEmpty && !entry.isPrivate
- }) map { entry => entry.defString }).mkString("{", "; ", "}")
- else
- ""
- }
- else if (sym.isRefinementClass && sym.isInitialized)
- thisInfo.toString
- else str
- }
-
- override def prefixString = "" + (
- if (settings.debug.value)
- super.prefixString
- else if (sym.printWithoutPrefix)
- ""
- else if (sym.isPackageClass)
- sym.fullName + "."
- else if (isStable && nme.isSingletonName(sym.name))
- nme.dropSingletonName(sym.name) + "."
- else
- super.prefixString
- )
- override def kind = "TypeRef"
- }
-
- object TypeRef extends TypeRefExtractor {
- def apply(pre: Type, sym: Symbol, args: List[Type]): Type = {
- unique(new TypeRef(pre, sym, args) with UniqueType)
- }
- }
-
- /** A class representing a method type with parameters.
- * Note that a parameterless method is represented by a NullaryMethodType:
- *
- * def m(): Int MethodType(Nil, Int)
- * def m: Int NullaryMethodType(Int)
- */
- case class MethodType(override val params: List[Symbol],
- override val resultType: Type) extends Type {
- override def isTrivial: Boolean = isTrivial0
- private lazy val isTrivial0 =
- resultType.isTrivial && params.forall{p => p.tpe.isTrivial && (
- !settings.YdepMethTpes.value || !(params.exists(_.tpe.contains(p)) || resultType.contains(p)))
- }
-
- def isImplicit = params.nonEmpty && params.head.isImplicit
- def isJava = false // can we do something like for implicits? I.e. do Java methods without parameters need to be recognized?
-
- //assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG
- override def paramSectionCount: Int = resultType.paramSectionCount + 1
-
- override def paramss: List[List[Symbol]] = params :: resultType.paramss
-
- override def paramTypes = params map (_.tpe)
-
- override def boundSyms = immutable.Set[Symbol](params ++ resultType.boundSyms: _*)
-
- // AM to TR: #dropNonContraintAnnotations
- // this is needed for plugins to work correctly, only TypeConstraint annotations are supposed to be carried over
- // TODO: this should probably be handled in a more structured way in adapt -- remove this map in resultType and watch the continuations tests fail
- object dropNonContraintAnnotations extends TypeMap {
- override val dropNonConstraintAnnotations = true
- def apply(x: Type) = mapOver(x)
- }
-
- override def resultType(actuals: List[Type]) =
- if (isTrivial) dropNonContraintAnnotations(resultType)
- else {
- if (sameLength(actuals, params)) {
- val idm = new InstantiateDependentMap(params, actuals)
- val res = idm(resultType)
- // println("resultTypeDep "+(params, actuals, resultType, idm.existentialsNeeded, "\n= "+ res))
- existentialAbstraction(idm.existentialsNeeded, res)
- } else {
- // Thread.dumpStack()
- // println("resultType "+(params, actuals, resultType))
- if (phase.erasedTypes) resultType
- else existentialAbstraction(params, resultType)
- }
- }
-
- // implicit args can only be depended on in result type: TODO this may be generalised so that the only constraint is dependencies are acyclic
- def approximate: MethodType = MethodType(params, resultApprox)
-
- override def finalResultType: Type = resultType.finalResultType
-
- override def safeToString = paramString(this) + resultType
-
- override def cloneInfo(owner: Symbol) = {
- val vparams = cloneSymbols(params, owner)
- copyMethodType(this, vparams, resultType.substSym(params, vparams).cloneInfo(owner))
- }
-
- override def atOwner(owner: Symbol) =
- if ((params exists (_.owner != owner)) || (resultType.atOwner(owner) ne resultType))
- cloneInfo(owner)
- else
- this
-
- override def kind = "MethodType"
- }
-
- object MethodType extends MethodTypeExtractor
-
- class JavaMethodType(ps: List[Symbol], rt: Type) extends MethodType(ps, rt) {
- override def isJava = true
- }
-
- case class NullaryMethodType(override val resultType: Type) extends Type {
- // AM to TR: #dropNonContraintAnnotations
- // change isTrivial to the commented version and watch continuations-run/t3225.scala fail
- // isTrivial implies asSeenFrom is bypassed, since it's supposed to be the identity map
- // it's not really the identity due to dropNonContraintAnnotations
- override def isTrivial: Boolean = false //resultType.isTrivial -- `false` to make continuations plugin work (so that asSeenFromMap drops non-constrain annotations even when type doesn't change otherwise)
- override def prefix: Type = resultType.prefix
- override def narrow: Type = resultType.narrow
- override def finalResultType: Type = resultType.finalResultType
- override def termSymbol: Symbol = resultType.termSymbol
- override def typeSymbol: Symbol = resultType.typeSymbol
- override def parents: List[Type] = resultType.parents
- override def decls: Scope = resultType.decls
- override def baseTypeSeq: BaseTypeSeq = resultType.baseTypeSeq
- override def baseTypeSeqDepth: Int = resultType.baseTypeSeqDepth
- override def baseClasses: List[Symbol] = resultType.baseClasses
- override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
- override def boundSyms = resultType.boundSyms
- override def isVolatile = resultType.isVolatile
- override def safeToString: String = "=> "+ resultType
- override def kind = "NullaryMethodType"
- }
-
- object NullaryMethodType extends NullaryMethodTypeExtractor
-
- /** A type function or the type of a polymorphic value (and thus of kind *).
- *
- * Before the introduction of NullaryMethodType, a polymorphic nullary method (e.g, def isInstanceOf[T]: Boolean)
- * used to be typed as PolyType(tps, restpe), and a monomorphic one as PolyType(Nil, restpe)
- * This is now: PolyType(tps, NullaryMethodType(restpe)) and NullaryMethodType(restpe)
- * by symmetry to MethodTypes: PolyType(tps, MethodType(params, restpe)) and MethodType(params, restpe)
- *
- * Thus, a PolyType(tps, TypeRef(...)) unambiguously indicates a type function (which results from eta-expanding a type constructor alias).
- * Similarly, PolyType(tps, ClassInfoType(...)) is a type constructor.
- *
- * A polytype is of kind * iff its resultType is a (nullary) method type.
- */
- case class PolyType(override val typeParams: List[Symbol], override val resultType: Type)
- extends Type {
- //assert(!(typeParams contains NoSymbol), this)
- assert(typeParams nonEmpty, this) // used to be a marker for nullary method type, illegal now (see @NullaryMethodType)
-
- override def paramSectionCount: Int = resultType.paramSectionCount
- override def paramss: List[List[Symbol]] = resultType.paramss
- override def params: List[Symbol] = resultType.params
- override def paramTypes: List[Type] = resultType.paramTypes
- override def parents: List[Type] = resultType.parents
- override def decls: Scope = resultType.decls
- override def termSymbol: Symbol = resultType.termSymbol
- override def typeSymbol: Symbol = resultType.typeSymbol
- override def boundSyms = immutable.Set[Symbol](typeParams ++ resultType.boundSyms: _*)
- override def prefix: Type = resultType.prefix
- override def baseTypeSeq: BaseTypeSeq = resultType.baseTypeSeq
- override def baseTypeSeqDepth: Int = resultType.baseTypeSeqDepth
- override def baseClasses: List[Symbol] = resultType.baseClasses
- override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
- override def narrow: Type = resultType.narrow
- override def isVolatile = resultType.isVolatile
- override def finalResultType: Type = resultType.finalResultType
-
- /** @M: typeDefSig wraps a TypeBounds in a PolyType
- * to represent a higher-kinded type parameter
- * wrap lo&hi in polytypes to bind variables
- */
- override def bounds: TypeBounds =
- TypeBounds(typeFun(typeParams, resultType.bounds.lo),
- typeFun(typeParams, resultType.bounds.hi))
-
- override def isHigherKinded = !typeParams.isEmpty
-
- override def safeToString = typeParamsString(this) + resultType
-
- override def cloneInfo(owner: Symbol) = {
- val tparams = cloneSymbols(typeParams, owner)
- PolyType(tparams, resultType.substSym(typeParams, tparams).cloneInfo(owner))
- }
-
- override def atOwner(owner: Symbol) =
- if ((typeParams exists (_.owner != owner)) || (resultType.atOwner(owner) ne resultType))
- cloneInfo(owner)
- else
- this
-
- override def kind = "PolyType"
- }
-
- object PolyType extends PolyTypeExtractor
-
- case class ExistentialType(quantified: List[Symbol],
- override val underlying: Type) extends RewrappingTypeProxy
- {
- override protected def rewrap(newtp: Type) = existentialAbstraction(quantified, newtp)
-
- override def isTrivial = false
- override def isStable: Boolean = false
- override def bounds = TypeBounds(maybeRewrap(underlying.bounds.lo), maybeRewrap(underlying.bounds.hi))
- override def parents = underlying.parents map maybeRewrap
- override def boundSyms = quantified.toSet
- override def prefix = maybeRewrap(underlying.prefix)
- override def typeArgs = underlying.typeArgs map maybeRewrap
- override def params = underlying.params mapConserve { param =>
- val tpe1 = rewrap(param.tpe)
- if (tpe1 eq param.tpe) param else param.cloneSymbol.setInfo(tpe1)
- }
- override def paramTypes = underlying.paramTypes map maybeRewrap
- override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = {
-// maybeRewrap(underlying.instantiateTypeParams(formals, actuals))
-
- val quantified1 = new SubstTypeMap(formals, actuals) mapOver quantified
- val underlying1 = underlying.instantiateTypeParams(formals, actuals)
- if ((quantified1 eq quantified) && (underlying1 eq underlying)) this
- else existentialAbstraction(quantified1, underlying1.substSym(quantified, quantified1))
-
- }
- override def baseType(clazz: Symbol) = maybeRewrap(underlying.baseType(clazz))
- override def baseTypeSeq = underlying.baseTypeSeq map maybeRewrap
- override def isHigherKinded = false
-
- override def skolemizeExistential(owner: Symbol, origin: AnyRef) = {
- def mkSkolem(tparam: Symbol): Symbol = {
- val skolem = new TypeSkolem(
- if (owner == NoSymbol) tparam.owner else owner,
- tparam.pos, tparam.name.toTypeName, origin)
- skolem.setInfo(tparam.info.cloneInfo(skolem))
- .setFlag(tparam.flags | EXISTENTIAL)
- .resetFlag(PARAM)
- }
- val skolems = quantified map mkSkolem
- for (skolem <- skolems)
- skolem setInfo skolem.info.substSym(quantified, skolems)
- underlying.substSym(quantified, skolems)
- }
-
- private def wildcardArgsString(available: Set[Symbol], args: List[Type]): List[String] = args match {
- case TypeRef(_, sym, _) :: args1 if (available contains sym) =>
- ("_"+sym.infoString(sym.info)) :: wildcardArgsString(available - sym, args1)
- case arg :: args1 if !(quantified exists (arg contains _)) =>
- arg.toString :: wildcardArgsString(available, args1)
- case _ =>
- List()
- }
-
- override def safeToString: String = {
- if (!(quantified exists (_.isSingletonExistential)) && !settings.debug.value)
- // try to represent with wildcards first
- underlying match {
- case TypeRef(pre, sym, args) if args.nonEmpty =>
- val wargs = wildcardArgsString(quantified.toSet, args)
- if (sameLength(wargs, args))
- return TypeRef(pre, sym, List()) + wargs.mkString("[", ", ", "]")
- case _ =>
- }
- var ustr = underlying.toString
- underlying match {
- case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) => ustr = "("+ustr+")"
- case _ =>
- }
- val str =
- ustr+(quantified map (_.existentialToString) mkString(" forSome { ", "; ", " }"))
- if (settings.explaintypes.value) "("+str+")" else str
- }
-
- override def cloneInfo(owner: Symbol) = {
- val tparams = cloneSymbols(quantified, owner)
- ExistentialType(tparams, underlying.substSym(quantified, tparams))
- }
-
- override def atOwner(owner: Symbol) =
- if (quantified exists (_.owner != owner)) cloneInfo(owner) else this
-
- override def kind = "ExistentialType"
-
- def withTypeVars(op: Type => Boolean): Boolean = withTypeVars(op, AnyDepth)
-
- def withTypeVars(op: Type => Boolean, depth: Int): Boolean = {
- val quantifiedFresh = cloneSymbols(quantified)
- val tvars = quantifiedFresh map (tparam => TypeVar(tparam))
- val underlying1 = underlying.instantiateTypeParams(quantified, tvars) // fuse subst quantified -> quantifiedFresh -> tvars
- op(underlying1) && {
- solve(tvars, quantifiedFresh, quantifiedFresh map (x => 0), false, depth) &&
- isWithinBounds(NoPrefix, NoSymbol, quantifiedFresh, tvars map (_.constr.inst))
- }
- }
- }
-
- object ExistentialType extends ExistentialTypeExtractor
-
- /** A class containing the alternatives and type prefix of an overloaded symbol.
- * Not used after phase `typer'.
- */
- case class OverloadedType(pre: Type, alternatives: List[Symbol]) extends Type {
- override def prefix: Type = pre
- override def safeToString =
- (alternatives map pre.memberType).mkString("", " <and> ", "")
- override def kind = "OverloadedType"
- }
-
- /** A class remembering a type instantiation for some a set of overloaded
- * polymorphic symbols.
- * Not used after phase `typer'.
- */
- case class AntiPolyType(pre: Type, targs: List[Type]) extends Type {
- override def safeToString =
- pre.toString + targs.mkString("(with type arguments ", ",", ")");
- override def memberType(sym: Symbol) = appliedType(pre.memberType(sym), targs)
-// override def memberType(sym: Symbol) = pre.memberType(sym) match {
-// case PolyType(tparams, restp) =>
-// restp.subst(tparams, targs)
-// /* I don't think this is needed, as existential types close only over value types
-// case ExistentialType(tparams, qtpe) =>
-// existentialAbstraction(tparams, qtpe.memberType(sym))
-// */
-// case ErrorType =>
-// ErrorType
-// }
- override def kind = "AntiPolyType"
- }
-
- //private var tidCount = 0 //DEBUG
-
- //@M
- // a TypeVar used to be a case class with only an origin and a constr
- // then, constr became mutable (to support UndoLog, I guess), but pattern-matching returned the original constr0 (a bug)
- // now, pattern-matching returns the most recent constr
- object TypeVar {
- // encapsulate suspension so we can automatically link the suspension of cloned typevars to their original if this turns out to be necessary
- def Suspension = new Suspension
- class Suspension {
- private val suspended = mutable.HashSet[TypeVar]()
- def suspend(tv: TypeVar): Unit = {
- tv.suspended = true
- suspended += tv
- }
- def resumeAll(): Unit = {
- for(tv <- suspended) {
- tv.suspended = false
- }
- suspended.clear
- }
- }
-
- def unapply(tv: TypeVar): Some[(Type, TypeConstraint)] = Some((tv.origin, tv.constr))
- def apply(origin: Type, constr: TypeConstraint) = new TypeVar(origin, constr, List(), List())
- def apply(tparam: Symbol) = new TypeVar(tparam.tpeHK, new TypeConstraint, List(), tparam.typeParams) // TODO why not initialise TypeConstraint with bounds of tparam?
- def apply(origin: Type, constr: TypeConstraint, args: List[Type], params: List[Symbol]) = new TypeVar(origin, constr, args, params)
- }
-
- /** A class representing a type variable
- * Not used after phase `typer'.
- * A higher-kinded type variable has type arguments (a list of Type's) and type parameters (list of Symbols)
- * A TypeVar whose list of args is non-empty can only be instantiated by a higher-kinded type that can be applied to these args
- * a typevar is much like a typeref, except it has special logic for type equality/subtyping
- */
- class TypeVar(val origin: Type, val constr0: TypeConstraint, override val typeArgs: List[Type], override val params: List[Symbol]) extends Type {
- // params are needed to keep track of variance (see mapOverArgs in SubstMap)
- assert(typeArgs.isEmpty || sameLength(typeArgs, params))
- // var tid = { tidCount += 1; tidCount } //DEBUG
-
- /** The constraint associated with the variable */
- var constr = constr0
- def instValid = constr.instValid
-
- /** The variable's skolemization level */
- val level = skolemizationLevel
-
- /**
- * two occurrences of a higher-kinded typevar, e.g. ?CC[Int] and ?CC[String], correspond to
- * *two instances* of TypeVar that share the *same* TypeConstraint
- * constr for ?CC only tracks type constructors anyway, so when ?CC[Int] <:< List[Int] and ?CC[String] <:< Iterable[String]
- * ?CC's hibounds contains List and Iterable
- */
- def applyArgs(newArgs: List[Type]): TypeVar =
- if (newArgs.isEmpty) this // SubstMap relies on this (though this check is redundant when called from appliedType...)
- else TypeVar(origin, constr, newArgs, params) // @M TODO: interaction with undoLog??
- // newArgs.length may differ from args.length (could've been empty before)
- // example: when making new typevars, you start out with C[A], then you replace C by ?C, which should yield ?C[A], then A by ?A, ?C[?A]
- // we need to track a TypeVar's arguments, and map over them (see TypeMap::mapOver)
- // TypeVars get applied to different arguments over time (in asSeenFrom)
- // -- see pos/tcpoly_infer_implicit_tuplewrapper.scala
- // thus: make new TypeVar's for every application of a TV to args,
- // inference may generate several TypeVar's for a single type parameter that must be inferred,
- // only one of them is in the set of tvars that need to be solved, but
- // they share the same TypeConstraint instance
-
- // <region name="constraint mutators + undoLog">
- // invariant: before mutating constr, save old state in undoLog (undoLog is used to reset constraints to avoid piling up unrelated ones)
- def setInst(tp: Type) {
-// assert(!(tp containsTp this), this)
- undoLog record this
- constr.inst = tp
- }
-
- def addLoBound(tp: Type, isNumericBound: Boolean = false) {
- assert(tp != this) // implies there is a cycle somewhere (?)
- //println("addLoBound: "+(safeToString, debugString(tp))) //DEBUG
- undoLog record this
- constr.addLoBound(tp, isNumericBound)
- }
-
- def addHiBound(tp: Type, isNumericBound: Boolean = false) {
- // assert(tp != this)
- //println("addHiBound: "+(safeToString, debugString(tp))) //DEBUG
- undoLog record this
- constr.addHiBound(tp, isNumericBound)
- }
- // </region>
-
- // ignore subtyping&equality checks while true -- see findMember
- private[TypeVar] var suspended = false
-
- /** Called when a TypeVar is involved in a subtyping check. Result is whether
- * this TypeVar could plausibly be a [super/sub]type of argument `tp` and if so,
- * tracks tp as a [lower/upper] bound of this TypeVar.
- *
- * if (isLowerBound) this typevar could be a subtype, track tp as a lower bound
- * if (!isLowerBound) this typevar could be a supertype, track tp as an upper bound
- *
- * If isNumericBound is true, the subtype check is performed with weak_<:< instead of <:<.
- */
- def registerBound(tp: Type, isLowerBound: Boolean, isNumericBound: Boolean = false): Boolean = {
- // println("regBound: "+(safeToString, debugString(tp), isLowerBound)) //@MDEBUG
- if (isLowerBound) assert(tp != this)
-
- def checkSubtypeLower(tp1: Type, tp2: Type) =
- if (isNumericBound) tp1 weak_<:< tp2
- else tp1 <:< tp2
-
- // swaps the arguments if it's an upper bound
- def checkSubtype(tp1: Type, tp2: Type) =
- if (isLowerBound) checkSubtypeLower(tp1, tp2)
- else checkSubtypeLower(tp2, tp1)
-
- def addBound(tp: Type) = {
- if (isLowerBound) addLoBound(tp, isNumericBound)
- else addHiBound(tp, isNumericBound)
- // println("addedBound: "+(this, tp)) // @MDEBUG
- true
- }
-
- /** Simple case: type arguments can be ignored, because either this typevar has
- * no type parameters, or we are comparing to Any/Nothing.
- *
- * The latter condition is needed because HK unification is limited to constraints of the shape
- * TC1[T1,..., TN] <: TC2[T'1,...,T'N]
- * which would preclude the following important constraints:
- * Nothing <: ?TC[?T]
- * ?TC[?T] <: Any
- */
- def unifySimple = (params.isEmpty || tp.typeSymbol == NothingClass || tp.typeSymbol == AnyClass) &&
- addBound(tp)
-
- /** Full case: involving a check of the form
- * TC1[T1,..., TN] <: TC2[T'1,...,T'N]
- * Checks subtyping of higher-order type vars, and uses variances as defined in the
- * type parameter we're trying to infer (the result will be sanity-checked later)
- */
- def unifyFull(tp: Type) = sameLength(typeArgs, tp.typeArgs) && { // this is a higher-kinded type var with same arity as tp
- // side effect: adds the type constructor itself as a bound
- addBound(tp.typeConstructor)
- if (isLowerBound) isSubArgs(tp.typeArgs, typeArgs, params)
- else isSubArgs(typeArgs, tp.typeArgs, params)
- }
-
- /** TODO: need positive/negative test cases demonstrating this is correct.
- */
- def unifyParents =
- if (isLowerBound) tp.parents exists unifyFull
- else tp.parents forall unifyFull
-
- // TODO: fancier unification, maybe rewrite constraint as follows?
- // val sym = constr.hiBounds map {_.typeSymbol} find { _.typeParams.length == typeArgs.length}
- // this <: tp.baseType(sym)
- if (suspended) checkSubtype(tp, origin)
- else if (constr.instValid) checkSubtype(tp, constr.inst) // type var is already set
- else isRelatable(tp) && {
- unifySimple || unifyFull(tp) || unifyFull(tp.dealias) || unifyFull(tp.widen) || unifyParents
- }
- }
-
- def registerTypeEquality(tp: Type, typeVarLHS: Boolean): Boolean = { //println("regTypeEq: "+(safeToString, debugString(tp), typeVarLHS)) //@MDEBUG
- def checkIsSameType(tp: Type) =
- if(typeVarLHS) constr.inst =:= tp
- else tp =:= constr.inst
-
- if (suspended) tp =:= origin
- else if (constr.instValid) checkIsSameType(tp)
- else isRelatable(tp) && {
- val newInst = wildcardToTypeVarMap(tp)
- if (constr.isWithinBounds(newInst)) {
- setInst(tp)
- true
- } else false
- }
- }
-
- /**
- * ?A.T =:= tp is rewritten as the constraint ?A <: {type T = tp}
- *
- * TODO: make these constraints count (incorporate them into implicit search in applyImplicitArgs)
- * (T corresponds to @param sym)
- */
- def registerTypeSelection(sym: Symbol, tp: Type): Boolean = {
- val bound = refinedType(List(WildcardType), NoSymbol)
- val bsym = bound.typeSymbol.newAliasType(NoPosition, sym.name.toTypeName)
- bsym setInfo tp
- bound.decls enter bsym
- registerBound(bound, false)
- }
-
- /** Can this variable be related in a constraint to type `tp'?
- * This is not the case if `tp' contains type skolems whose
- * skolemization level is higher than the level of this variable.
- */
- def isRelatable(tp: Type): Boolean =
- !tp.exists { t =>
- t.typeSymbol match {
- case ts: TypeSkolem => ts.level > level
- case _ => false
- }
- }
-
- override val isHigherKinded = typeArgs.isEmpty && params.nonEmpty
-
- override def normalize: Type =
- if (constr.instValid) constr.inst
- // get here when checking higher-order subtyping of the typevar by itself
- // TODO: check whether this ever happens?
- else if (isHigherKinded) typeFun(params, applyArgs(params map (_.typeConstructor)))
- else super.normalize
-
- override def typeSymbol = origin.typeSymbol
- override def isStable = origin.isStable
- override def isVolatile = origin.isVolatile
-
- private def levelString = if (settings.explaintypes.value) level else ""
- override def safeToString = constr.inst match {
- case null => "<null " + origin + ">"
- case NoType => "?" + levelString + origin + typeArgsString(this)
- case x => "" + x
- }
- override def kind = "TypeVar"
-
- def cloneInternal = {
- // cloning a suspended type variable when it's suspended will cause the clone
- // to never be resumed with the current implementation
- assert(!suspended)
- TypeVar(origin, constr cloneInternal, typeArgs, params) // @M TODO: clone args/params?
- }
- }
-
- /** A type carrying some annotations. Created by the typechecker
- * when eliminating ``Annotated'' trees (see typedAnnotated).
- *
- * @param annotations the list of annotations on the type
- * @param underlying the type without the annotation
- * @param selfsym a "self" symbol with type <code>underlying</code>;
- * only available if -Yself-in-annots is turned on. Can be NoSymbol
- * if it is not used.
- */
- case class AnnotatedType(override val annotations: List[AnnotationInfo],
- override val underlying: Type,
- override val selfsym: Symbol)
- extends RewrappingTypeProxy {
-
- assert(!annotations.isEmpty)
-
- override protected def rewrap(tp: Type) = AnnotatedType(annotations, tp, selfsym)
-
- override def isTrivial: Boolean = isTrivial0
- private lazy val isTrivial0 = underlying.isTrivial && (annotations forall (_.isTrivial))
-
- override def safeToString: String = {
- val attString =
- if (annotations.isEmpty)
- ""
- else
- annotations.mkString(" @", " @", "")
-
- underlying + attString
- }
-
- /** Add a number of annotations to this type */
- override def withAnnotations(annots: List[AnnotationInfo]): Type =
- copy(annots:::this.annotations)
-
- /** Remove any annotations from this type */
- override def withoutAnnotations = underlying.withoutAnnotations
-
- /** Set the self symbol */
- override def withSelfsym(sym: Symbol) =
- AnnotatedType(annotations, underlying, sym)
-
- /** Drop the annotations on the bounds, unless but the low and high
- * bounds are exactly tp.
- */
- override def bounds: TypeBounds = underlying.bounds match {
- case TypeBounds(_: this.type, _: this.type) => TypeBounds(this, this)
- case oftp => oftp
- }
-
- // ** Replace formal type parameter symbols with actual type arguments. * /
- override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = {
- val annotations1 = annotations.map(info => AnnotationInfo(info.atp.instantiateTypeParams(
- formals, actuals), info.args, info.assocs).setPos(info.pos))
- val underlying1 = underlying.instantiateTypeParams(formals, actuals)
- if ((annotations1 eq annotations) && (underlying1 eq underlying)) this
- else AnnotatedType(annotations1, underlying1, selfsym)
- }
-
- /** Return the base type sequence of tp, dropping the annotations, unless the base type sequence of tp
- * is precisely tp itself. */
- override def baseTypeSeq: BaseTypeSeq = {
- val oftp = underlying.baseTypeSeq
- if ((oftp.length == 1) && (oftp(0) eq underlying))
- baseTypeSingletonSeq(this)
- else
- oftp
- }
-
- override def kind = "AnnotatedType"
- }
-
- object AnnotatedType extends AnnotatedTypeExtractor
-
- /** A class representing types with a name. When an application uses
- * named arguments, the named argument types for calling isApplicable
- * are represented as NamedType.
- */
- case class NamedType(name: Name, tp: Type) extends Type {
- override def safeToString: String = name.toString +": "+ tp
- }
-
- /** A class representing an as-yet unevaluated type.
- */
- abstract class LazyType extends Type with AbsLazyType {
- override def kind = "LazyType"
- }
-
-// Creators ---------------------------------------------------------------
-
- /** Rebind symbol `sym' to an overriding member in type
- * `pre'.
- */
- private def rebind(pre: Type, sym: Symbol): Symbol = {
- val owner = sym.owner
- if (owner.isClass && owner != pre.typeSymbol && !sym.isEffectivelyFinal && !sym.isClass) {
- //Console.println("rebind "+pre+" "+sym)//DEBUG
- val rebind = pre.nonPrivateMember(sym.name).suchThat(sym => sym.isType || sym.isStable)
- if (rebind == NoSymbol) sym
- else {
- // Console.println("rebound "+pre+" "+sym+" to "+rebind)//DEBUG
- rebind
- }
- } else sym
- }
-
- /** Convert a `super' prefix to a this-type if `sym'
- * is abstract or final.
- */
- private def removeSuper(tp: Type, sym: Symbol): Type = tp match {
- case SuperType(thistp, _) =>
- if (sym.isEffectivelyFinal || sym.isDeferred) thistp
- else tp
- case _ =>
- tp
- }
-
- /** The canonical creator for single-types */
- def singleType(pre: Type, sym: Symbol): Type = {
- if (phase.erasedTypes)
- sym.tpe.resultType
- else if (sym.isRootPackage)
- ThisType(RootClass)
- else {
- var sym1 = rebind(pre, sym)
- val pre1 = removeSuper(pre, sym1)
- if (pre1 ne pre) sym1 = rebind(pre1, sym1)
- // why not do the hash-consing in the SingleType.apply()
- // factory, like the other UniqueTypes?
- unique(new SingleType(pre1, sym1) with UniqueType)
- }
- }
-
- /** the canonical creator for a refined type with a given scope */
- def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos : Position): Type = {
- if (phase.erasedTypes)
- if (parents.isEmpty) ObjectClass.tpe else parents.head
- else {
- val clazz = owner.newRefinementClass(NoPosition)
- val result = RefinedType(parents, decls, clazz)
- clazz.setInfo(result)
- result
- }
- }
-
- /** The canonical creator for a refined type with an initially empty scope.
- *
- * @param parents ...
- * @param owner ...
- * @return ...
- */
- def refinedType(parents: List[Type], owner: Symbol): Type =
- refinedType(parents, owner, new Scope, owner.pos)
-
- def copyRefinedType(original: RefinedType, parents: List[Type], decls: Scope) =
- if ((parents eq original.parents) && (decls eq original.decls)) original
- else {
- val owner = if (original.typeSymbol == NoSymbol) NoSymbol else original.typeSymbol.owner
- val result = refinedType(parents, owner)
- val syms1 = decls.toList
- for (sym <- syms1)
- result.decls.enter(sym.cloneSymbol(result.typeSymbol))
- val syms2 = result.decls.toList
- val resultThis = result.typeSymbol.thisType
- for (sym <- syms2)
- sym.setInfo(sym.info.substThis(original.typeSymbol, resultThis).substSym(syms1, syms2))
- result
- }
-
- /** The canonical creator for typerefs
- * todo: see how we can clean this up a bit
- */
- def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = {
- // type alias selections are rebound in TypeMap ("coevolved", actually -- see #3731)
- // e.g., when type parameters that are referenced by the alias are instantiated in
- // the prefix. See pos/depmet_rebind_typealias.
- def rebindTR(pre: Type, sym: Symbol) =
- if (sym.isAbstractType) rebind(pre, sym) else sym
-
- val sym1 = rebindTR(pre, sym)
-
- // we require that object is initialized, thus info.typeParams instead of typeParams.
- if (sym1.isAliasType && sameLength(sym1.info.typeParams, args)) {
- if (sym1.lockOK) TypeRef(pre, sym1, args) // don't expand type alias (cycles checked by lockOK)
- else throw new TypeError("illegal cyclic reference involving " + sym1)
- }
- else {
- val pre1 = removeSuper(pre, sym1)
- if (pre1 ne pre)
- typeRef(pre1, rebindTR(pre1, sym1), args)
- else pre match {
- case _: CompoundType if sym1.isClass =>
- // sharpen prefix so that it is maximal and still contains the class.
- pre.parents.reverse dropWhile (_.member(sym1.name) != sym1) match {
- case Nil => TypeRef(pre, sym1, args)
- case parent :: _ => typeRef(parent, sym1, args)
- }
- case _ =>
- TypeRef(pre, sym1, args)
- }
- }
- }
-
- /** The canonical creator for implicit method types */
- def JavaMethodType(params: List[Symbol], resultType: Type): JavaMethodType =
- new JavaMethodType(params, resultType) // don't unique this!
-
- /** Create a new MethodType of the same class as tp, i.e. keep JavaMethodType */
- def copyMethodType(tp: Type, params: List[Symbol], restpe: Type): Type = tp match {
- case _: JavaMethodType => JavaMethodType(params, restpe)
- case _ => MethodType(params, restpe)
- }
-
- /** A creator for intersection type where intersections of a single type are
- * replaced by the type itself, and repeated parent classes are merged.
- */
- def intersectionType(tps: List[Type], owner: Symbol): Type = tps match {
- case List(tp) =>
- tp
- case _ =>
- refinedType(tps, owner)
-/*
- def merge(tps: List[Type]): List[Type] = tps match {
- case tp :: tps1 =>
- val tps1a = tps1 filter (_.typeSymbol.==(tp.typeSymbol))
- val tps1b = tps1 filter (_.typeSymbol.!=(tp.typeSymbol))
- mergePrefixAndArgs(tps1a, -1) match {
- case Some(tp1) => tp1 :: merge(tps1b)
- case None => throw new MalformedType(
- "malformed type: "+refinedType(tps, owner)+" has repeated parent class "+
- tp.typeSymbol+" with incompatible prefixes or type arguments")
- }
- case _ => tps
- }
- refinedType(merge(tps), owner)
-*/
- }
-
- /** A creator for intersection type where intersections of a single type are
- * replaced by the type itself. */
- def intersectionType(tps: List[Type]): Type = tps match {
- case List(tp) => tp
- case _ => refinedType(tps, commonOwner(tps))
- }
-
- /** A creator for type applications */
- def appliedType(tycon: Type, args: List[Type]): Type =
- if (args.isEmpty) tycon //@M! `if (args.isEmpty) tycon' is crucial (otherwise we create new types in phases after typer and then they don't get adapted (??))
- else tycon match {
- case TypeRef(pre, sym @ (NothingClass|AnyClass), _) => typeRef(pre, sym, Nil) //@M drop type args to Any/Nothing
- case TypeRef(pre, sym, _) => typeRef(pre, sym, args)
- case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args)
- case ExistentialType(tparams, restpe) => ExistentialType(tparams, appliedType(restpe, args))
- case st: SingletonType => appliedType(st.widen, args) // @M TODO: what to do? see bug1
- case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // MO to AM: please check
- case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args))
- case tv@TypeVar(_, _) => tv.applyArgs(args)
- case AnnotatedType(annots, underlying, self) => AnnotatedType(annots, appliedType(underlying, args), self)
- case ErrorType => tycon
- case WildcardType => tycon // needed for neg/t0226
- case _ => abort(debugString(tycon))
- }
-
- /** A creator for type parameterizations that strips empty type parameter lists.
- * Use this factory method to indicate the type has kind * (it's a polymorphic value)
- * until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty)
- */
- def polyType(tparams: List[Symbol], tpe: Type): Type =
- if (tparams nonEmpty) typeFun(tparams, tpe)
- else tpe // it's okay to be forgiving here
-
- /** A creator for anonymous type functions, where the symbol for the type function still needs to be created
- *
- * TODO:
- * type params of anonymous type functions, which currently can only arise from normalising type aliases, are owned by the type alias of which they are the eta-expansion
- * higher-order subtyping expects eta-expansion of type constructors that arise from a class; here, the type params are owned by that class, but is that the right thing to do?
- */
- def typeFunAnon(tps: List[Symbol], body: Type): Type = typeFun(tps, body)
-
- /** A creator for a type functions, assuming the type parameters tps already have the right owner
- */
- def typeFun(tps: List[Symbol], body: Type): Type = PolyType(tps, body)
-
- /** A creator for existential types. This generates:
- *
- * tpe1 where { tparams }
- *
- * where `tpe1' is the result of extrapolating `tpe' wrt to `tparams'. Extrapolating means
- * that type variables in `tparams' occurring in covariant positions are replaced by upper bounds,
- * (minus any SingletonClass markers),
- * type variables in `tparams' occurring in contravariant positions are replaced by upper bounds,
- * provided the resulting type is legal wrt to stability, and does not contain any
- * type variable in `tparams'.
- * The abstraction drops all type parameters that are not directly or indirectly
- * referenced by type `tpe1'.
- * If there are no remaining type parameters, simply returns result type `tpe'.
- */
- def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type =
- if (tparams.isEmpty) tpe0
- else {
- var occurCount = emptySymCount ++ (tparams map (_ -> 0))
- val tpe = deAlias(tpe0)
- def countOccs(tp: Type) =
- for (t <- tp) {
- t match {
- case TypeRef(_, sym, _) =>
- occurCount get sym match {
- case Some(count) => occurCount += (sym -> (count + 1))
- case none =>
- }
- case _ =>
- }
- }
- countOccs(tpe)
- for (tparam <- tparams) countOccs(tparam.info)
-
- val extrapolate = new TypeMap {
- variance = 1
- def apply(tp: Type): Type = {
- val tp1 = mapOver(tp)
- tp1 match {
- case TypeRef(pre, sym, args) if (variance != 0) && (occurCount isDefinedAt sym) =>
- val repl = if (variance == 1) dropSingletonType(tp1.bounds.hi) else tp1.bounds.lo
- //println("eliminate "+sym+"/"+repl+"/"+occurCount(sym)+"/"+(tparams exists (repl.contains)))//DEBUG
- if (repl.typeSymbol != NothingClass && repl.typeSymbol != NullClass &&
- occurCount(sym) == 1 && !(tparams exists (repl.contains)))
- repl
- else tp1
- case _ =>
- tp1
- }
- }
- override def mapOver(tp: Type): Type = tp match {
- case SingleType(pre, sym) =>
- if (sym.isPackageClass) tp // short path
- else {
- val pre1 = this(pre)
- if ((pre1 eq pre) || !pre1.isStable) tp
- else singleType(pre1, sym)
- }
- case _ => super.mapOver(tp)
- }
-
- override def mapOver(tree: Tree) =
- tree match {
- case tree:Ident if tree.tpe.isStable =>
- // Do not discard the types of existential ident's.
- // The symbol of the Ident itself cannot be listed
- // in the existential's parameters, so the
- // resulting existential type would be ill-formed.
- Some(tree)
-
- case _ =>
- super.mapOver(tree)
- }
- }
- val tpe1 = extrapolate(tpe)
- var tparams0 = tparams
- var tparams1 = tparams0 filter tpe1.contains
-
- while (tparams1 != tparams0) {
- tparams0 = tparams1
- tparams1 = tparams filter { p =>
- tparams1 exists { p1 => p1 == p || (p1.info contains p) }
- }
- }
- if (tparams1.isEmpty) tpe1
- else tpe1 match {
- case ExistentialType(tparams2, tpe2) => ExistentialType(tparams1 ::: tparams2, tpe2)
- case _ => ExistentialType(tparams1, tpe1)
- }
- }
-
- /** Remove any occurrences of type aliases from this type */
- object deAlias extends TypeMap {
- def apply(tp: Type): Type = mapOver {
- tp match {
- case TypeRef(pre, sym, args) if sym.isAliasType => tp.normalize
- case _ => tp
- }
- }
- }
-
- /** Remove any occurrence of type <singleton> from this type and its parents */
- object dropSingletonType extends TypeMap {
- def apply(tp: Type): Type = {
- tp match {
- case TypeRef(_, SingletonClass, _) =>
- AnyClass.tpe
- case tp1 @ RefinedType(parents, decls) =>
- var parents1 = parents filter (_.typeSymbol != SingletonClass)
- if (parents1.isEmpty) parents1 = List(AnyClass.tpe)
- if (parents1.tail.isEmpty && decls.isEmpty) mapOver(parents1.head)
- else mapOver(copyRefinedType(tp1, parents1, decls))
- case tp1 =>
- mapOver(tp1)
- }
- }
- }
-
-// Hash consing --------------------------------------------------------------
-
- private val initialUniquesCapacity = 4096
- private var uniques: util.HashSet[Type] = _
- private var uniqueRunId = NoRunId
-
- private def unique[T <: Type](tp: T): T = {
- incCounter(rawTypeCount)
- if (uniqueRunId != currentRunId) {
- uniques = util.HashSet[Type]("uniques", initialUniquesCapacity)
- uniqueRunId = currentRunId
- }
- (uniques findEntryOrUpdate tp).asInstanceOf[T]
- }
-
-// Helper Classes ---------------------------------------------------------
-
- /** @PP: Unable to see why these apparently constant types should need vals
- * in every TypeConstraint, I lifted them out.
- */
- private lazy val numericLoBound = IntClass.tpe
- private lazy val numericHiBound = intersectionType(List(ByteClass.tpe, CharClass.tpe), ScalaPackageClass)
-
- /** A class expressing upper and lower bounds constraints of type variables,
- * as well as their instantiations.
- */
- class TypeConstraint(lo0: List[Type], hi0: List[Type], numlo0: Type, numhi0: Type) {
- def this(lo0: List[Type], hi0: List[Type]) = this(lo0, hi0, NoType, NoType)
- def this() = this(List(), List())
-
- private var lobounds = lo0
- private var hibounds = hi0
- private var numlo = numlo0
- private var numhi = numhi0
-
- def loBounds: List[Type] = if (numlo == NoType) lobounds else numlo :: lobounds
- def hiBounds: List[Type] = if (numhi == NoType) hibounds else numhi :: hibounds
-
- def addLoBound(tp: Type, isNumericBound: Boolean = false) {
- if (isNumericBound && isNumericValueType(tp)) {
- if (numlo == NoType || isNumericSubType(numlo, tp))
- numlo = tp
- else if (!isNumericSubType(tp, numlo))
- numlo = numericLoBound
- }
- else lobounds ::= tp
- }
-
- def addHiBound(tp: Type, isNumericBound: Boolean = false) {
- if (isNumericBound && isNumericValueType(tp)) {
- if (numhi == NoType || isNumericSubType(tp, numhi))
- numhi = tp
- else if (!isNumericSubType(numhi, tp))
- numhi = numericHiBound
- }
- else hibounds ::= tp
- }
-
- def isWithinBounds(tp: Type): Boolean =
- lobounds.forall(_ <:< tp) &&
- hibounds.forall(tp <:< _) &&
- (numlo == NoType || (numlo weak_<:< tp)) &&
- (numhi == NoType || (tp weak_<:< numhi))
-
- var inst: Type = NoType // @M reduce visibility?
-
- def instValid = (inst ne null) && (inst ne NoType)
-
- def cloneInternal = {
- val tc = new TypeConstraint(lobounds, hibounds, numlo, numhi)
- tc.inst = inst
- tc
- }
-
- override def toString =
- (loBounds map (_.safeToString)).mkString("[ _>:(", ",", ") ") +
- (hiBounds map (_.safeToString)).mkString("| _<:(", ",", ") ] _= ") +
- inst.safeToString
- }
-
- /** A prototype for mapping a function over all possible types
- */
- abstract class TypeMap extends Function1[Type, Type] {
- // deferred inherited: def apply(tp: Type): Type
-
- /** The variance relative to start. If you want variances to be significant, set
- * variance = 1
- * at the top of the typemap.
- */
- var variance = 0
-
- /** Should this map drop annotations that are not
- * type-constraint annotations?
- */
- val dropNonConstraintAnnotations = false
-
- /** Check whether two lists have elements that are eq-equal */
- def allEq[T <: AnyRef](l1: List[T], l2: List[T]) =
- (l1 corresponds l2)(_ eq _)
-
- // #3731: return sym1 for which holds: pre bound sym.name to sym and pre1 now binds sym.name to sym1, conceptually exactly the same symbol as sym
- // the selection of sym on pre must be updated to the selection of sym1 on pre1,
- // since sym's info was probably updated by the TypeMap to yield a new symbol sym1 with transformed info
- // @returns sym1
- protected def coevolveSym(pre: Type, pre1: Type, sym: Symbol): Symbol =
- if((pre ne pre1) && sym.isAliasType) // only need to rebind type aliases here, as typeRef already handles abstract types (they are allowed to be rebound more liberally)
- (pre, pre1) match {
- case (RefinedType(_, decls), RefinedType(_, decls1)) => // don't look at parents -- it would be an error to override alias types anyway
- //val sym1 =
- decls1.lookup(sym.name)
-// assert(decls.lookupAll(sym.name).toList.length == 1)
-// assert(decls1.lookupAll(sym.name).toList.length == 1)
-// assert(sym1.isAliasType)
-// println("coevolved "+ sym +" : "+ sym.info +" to "+ sym1 +" : "+ sym1.info +" with "+ pre +" -> "+ pre1)
-// sym1
- case _ => // TODO: is there another way a typeref's symbol can refer to a symbol defined in its pre?
-// val sym1 = pre1.nonPrivateMember(sym.name).suchThat(sym => sym.isAliasType)
-// println("??coevolve "+ sym +" : "+ sym.info +" to "+ sym1 +" : "+ sym1.info +" with "+ pre +" -> "+ pre1)
- sym
- }
- else sym
-
- /** Map this function over given type */
- def mapOver(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) =>
- val pre1 = this(pre)
- //val args1 = args mapConserve this(_)
- val args1 = if (args.isEmpty) args
- else {
- val tparams = sym.typeParams
- if (tparams.isEmpty) args
- else mapOverArgs(args, tparams)
- }
- if ((pre1 eq pre) && (args1 eq args)) tp
- else typeRef(pre1, coevolveSym(pre, pre1, sym), args1)
- case ThisType(_) => tp
- case SingleType(pre, sym) =>
- if (sym.isPackageClass) tp // short path
- else {
- val pre1 = this(pre)
- if (pre1 eq pre) tp
- else singleType(pre1, sym)
- }
- case MethodType(params, result) =>
- variance = -variance
- val params1 = mapOver(params)
- variance = -variance
- val result1 = this(result)
- if ((params1 eq params) && (result1 eq result)) tp
- // for new dependent types: result1.substSym(params, params1)?
- else copyMethodType(tp, params1, result1.substSym(params, params1))
- case PolyType(tparams, result) =>
- variance = -variance
- val tparams1 = mapOver(tparams)
- variance = -variance
- var result1 = this(result)
- if ((tparams1 eq tparams) && (result1 eq result)) tp
- else PolyType(tparams1, result1.substSym(tparams, tparams1))
- case NullaryMethodType(result) =>
- val result1 = this(result)
- if (result1 eq result) tp
- else NullaryMethodType(result1)
- case ConstantType(_) => tp
- case SuperType(thistp, supertp) =>
- val thistp1 = this(thistp)
- val supertp1 = this(supertp)
- if ((thistp1 eq thistp) && (supertp1 eq supertp)) tp
- else SuperType(thistp1, supertp1)
- case TypeBounds(lo, hi) =>
- variance = -variance
- val lo1 = this(lo)
- variance = -variance
- val hi1 = this(hi)
- if ((lo1 eq lo) && (hi1 eq hi)) tp
- else TypeBounds(lo1, hi1)
- case BoundedWildcardType(bounds) =>
- val bounds1 = this(bounds)
- if (bounds1 eq bounds) tp
- else BoundedWildcardType(bounds1.asInstanceOf[TypeBounds])
- case rtp @ RefinedType(parents, decls) =>
- val parents1 = parents mapConserve (this)
- val decls1 = mapOver(decls)
- //if ((parents1 eq parents) && (decls1 eq decls)) tp
- //else refinementOfClass(tp.typeSymbol, parents1, decls1)
- copyRefinedType(rtp, parents1, decls1)
- case ExistentialType(tparams, result) =>
- val tparams1 = mapOver(tparams)
- var result1 = this(result)
- if ((tparams1 eq tparams) && (result1 eq result)) tp
- else ExistentialType(tparams1, result1.substSym(tparams, tparams1))
- case OverloadedType(pre, alts) =>
- val pre1 = if (pre.isInstanceOf[ClassInfoType]) pre else this(pre)
- if (pre1 eq pre) tp
- else OverloadedType(pre1, alts)
- case AntiPolyType(pre, args) =>
- val pre1 = this(pre)
- val args1 = args mapConserve (this)
- if ((pre1 eq pre) && (args1 eq args)) tp
- else AntiPolyType(pre1, args1)
- case tv@TypeVar(_, constr) =>
- if (constr.instValid) this(constr.inst)
- else tv.applyArgs(mapOverArgs(tv.typeArgs, tv.params)) //@M !args.isEmpty implies !typeParams.isEmpty
- case NotNullType(tp) =>
- val tp1 = this(tp)
- if (tp1 eq tp) tp
- else NotNullType(tp1)
- case AnnotatedType(annots, atp, selfsym) =>
- val annots1 = mapOverAnnotations(annots)
- val atp1 = this(atp)
- if ((annots1 eq annots) && (atp1 eq atp)) tp
- else if (annots1.isEmpty) atp1
- else AnnotatedType(annots1, atp1, selfsym)
-/*
- case ErrorType => tp
- case WildcardType => tp
- case NoType => tp
- case NoPrefix => tp
-*/
- case _ =>
- tp
- // throw new Error("mapOver inapplicable for " + tp);
- }
-
- def mapOverArgs(args: List[Type], tparams: List[Symbol]): List[Type] =
- map2Conserve(args, tparams) { (arg, tparam) =>
- val v = variance
- if (tparam.isContravariant) variance = -variance
- else if (!tparam.isCovariant) variance = 0
- val arg1 = this(arg)
- variance = v
- arg1
- }
-
- /** Map this function over given scope */
- def mapOver(scope: Scope): Scope = {
- val elems = scope.toList
- val elems1 = mapOver(elems)
- if (elems1 eq elems) scope
- else new Scope(elems1)
- }
-
- /** Map this function over given list of symbols */
- def mapOver(origSyms: List[Symbol]): List[Symbol] = {
- val change = origSyms exists { sym =>
- val v = variance
- if (sym.isAliasType) variance = 0
- val result = this(sym.info)
- variance = v
- result ne sym.info
- }
- if (!change) origSyms // fast path in case nothing changes due to map
- else { // map is not the identity --> do cloning properly
- val clonedSyms = origSyms map (_.cloneSymbol)
- val clonedInfos = clonedSyms map (_.info.substSym(origSyms, clonedSyms))
- val transformedInfos = clonedInfos mapConserve (this)
- (clonedSyms, transformedInfos).zipped map (_ setInfo _)
-
- clonedSyms
- }
- }
-
-
- def mapOverAnnotations(annots: List[AnnotationInfo])
- : List[AnnotationInfo] = {
- val newAnnots = annots.flatMap(mapOver(_))
- if (allEq(newAnnots, annots))
- annots
- else
- newAnnots
- }
-
- def mapOver(annot: AnnotationInfo): Option[AnnotationInfo] = {
- val AnnotationInfo(atp, args, assocs) = annot
-
- if (dropNonConstraintAnnotations &&
- !(atp.typeSymbol isNonBottomSubClass TypeConstraintClass))
- return None
-
- val atp1 = mapOver(atp)
- val args1 = mapOverAnnotArgs(args)
- // there is no need to rewrite assocs, as they are constants
-
- if ((args eq args1) && (atp eq atp1))
- Some(annot)
- else if (sameLength(args1, args))
- Some(AnnotationInfo(atp1, args1, assocs).setPos(annot.pos))
- else
- None
- }
-
- /** Map over a set of annotation arguments. If any
- * of the arguments cannot be mapped, then return Nil. */
- def mapOverAnnotArgs(args: List[Tree]): List[Tree] = {
- val args1 = args flatMap (x => mapOver(x))
- if (!sameLength(args1, args))
- Nil
- else if (allEq(args, args1))
- args
- else
- args1
- }
-
- def mapOver(tree: Tree): Option[Tree] =
- Some(mapOver(tree, ()=>return None))
-
- /** Map a tree that is part of an annotation argument.
- * If the tree cannot be mapped, then invoke giveup().
- * The default is to transform the tree with
- * TypeMapTransformer.
- */
- def mapOver(tree: Tree, giveup: ()=>Nothing): Tree =
- (new TypeMapTransformer).transform(tree)
-
- /** This transformer leaves the tree alone except to remap
- * its types. */
- class TypeMapTransformer extends Transformer {
- override def transform(tree: Tree) = {
- val tree1 = super.transform(tree)
- val tpe1 = TypeMap.this(tree1.tpe)
- if ((tree eq tree1) && (tree.tpe eq tpe1))
- tree
- else
- tree1.shallowDuplicate.setType(tpe1)
- }
- }
- }
-
- /** A type map that always returns the input type unchanged */
- object IdentityTypeMap extends TypeMap {
- def apply(tp: Type) = tp
- }
-
- abstract class TypeTraverser extends TypeMap {
- def traverse(tp: Type): Unit
- def apply(tp: Type): Type = { traverse(tp); tp }
- }
-
- abstract class TypeCollector[T](initial: T) extends TypeTraverser {
- var result: T = _
- def collect(tp: Type) = {
- result = initial
- traverse(tp)
- result
- }
- }
-
- private val emptySymMap = immutable.Map[Symbol, Symbol]()
- private val emptySymCount = immutable.Map[Symbol, Int]()
-
- def typeParamsToExistentials(clazz: Symbol, tparams: List[Symbol]): List[Symbol] = {
- val eparams = for ((tparam, i) <- tparams.zipWithIndex) yield {
- clazz.newExistential(clazz.pos, newTypeName("?"+i)).setInfo(tparam.info.bounds)
- }
- for (tparam <- eparams) tparam setInfo tparam.info.substSym(tparams, eparams)
- eparams
- }
-
- // note: it's important to write the two tests in this order,
- // as only typeParams forces the classfile to be read. See #400
- private def isRawIfWithoutArgs(sym: Symbol) =
- sym.isClass && sym.typeParams.nonEmpty && sym.isJavaDefined
-
- def isRaw(sym: Symbol, args: List[Type]) =
- !phase.erasedTypes && isRawIfWithoutArgs(sym) && args.isEmpty
-
- /** Is type tp a ``raw type''? */
- def isRawType(tp: Type) = tp match {
- case TypeRef(_, sym, args) => isRaw(sym, args)
- case _ => false
- }
-
- /** The raw to existential map converts a ``raw type'' to an existential type.
- * It is necessary because we might have read a raw type of a
- * parameterized Java class from a class file. At the time we read the type
- * the corresponding class file might still not be read, so we do not
- * know what the type parameters of the type are. Therefore
- * the conversion of raw types to existential types might not have taken place
- * in ClassFileparser.sigToType (where it is usually done)
- */
- object rawToExistential extends TypeMap {
- private var expanded = immutable.Set[Symbol]()
- def apply(tp: Type): Type = tp match {
- case TypeRef(pre, sym, List()) if isRawIfWithoutArgs(sym) =>
- if (expanded contains sym) AnyRefClass.tpe
- else try {
- expanded += sym
- val eparams = mapOver(typeParamsToExistentials(sym, sym.typeParams))
- existentialAbstraction(eparams, typeRef(apply(pre), sym, eparams map (_.tpe)))
- } finally {
- expanded -= sym
- }
- case ExistentialType(_, _) => // stop to avoid infinite expansions
- tp
- case _ =>
- mapOver(tp)
- }
- }
-
- def singletonBounds(hi: Type) = {
- TypeBounds.upper(intersectionType(List(hi, SingletonClass.tpe)))
- }
-
- /** A map to compute the asSeenFrom method */
- class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap {
- override val dropNonConstraintAnnotations = true
-
- var capturedParams: List[Symbol] = List()
-
- override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
- object annotationArgRewriter extends TypeMapTransformer {
- /** Rewrite `This` trees in annotation argument trees */
- def rewriteThis(tree: Tree): Tree =
- tree match {
- case This(_)
- if (tree.symbol isNonBottomSubClass clazz) &&
- (pre.widen.typeSymbol isNonBottomSubClass tree.symbol) =>
- if (pre.isStable) { // XXX why is this in this method? pull it out and guard the call `annotationArgRewriter.transform(tree)`?
- val termSym =
- pre.typeSymbol.owner.newValue(
- pre.typeSymbol.pos,
- pre.typeSymbol.name.toTermName).setInfo(pre) // what symbol should really be used?
- mkAttributedQualifier(pre, termSym)
- } else
- giveup()
-
- case tree => tree
- }
-
- override def transform(tree: Tree): Tree = {
- val tree1 = rewriteThis(super.transform(tree))
- tree1
- }
- }
-
- annotationArgRewriter.transform(tree)
- }
-
- var capturedPre = emptySymMap
-
- def stabilize(pre: Type, clazz: Symbol): Type =
- capturedPre.getOrElse(clazz, {
- val qvar = clazz freshExistential ".type" setInfo singletonBounds(pre)
- capturedPre += (clazz -> qvar)
- capturedParams = qvar :: capturedParams
- qvar
- }).tpe
-
- /** Return pre.baseType(clazz), or if that's NoType and clazz is a refinement, pre itself.
- * See bug397.scala for an example where the second alternative is needed.
- * The problem is that when forming the base type sequence of an abstract type,
- * any refinements in the base type list might be regenerated, and thus acquire
- * new class symbols. However, since refinements always have non-interesting prefixes
- * it looks OK to me to just take the prefix directly. */
- def base(pre: Type, clazz: Symbol) = {
- val b = pre.baseType(clazz)
- if (b == NoType && clazz.isRefinementClass) pre
- else b
- }
-
- def apply(tp: Type): Type =
- if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) tp
- else tp match {
- case ThisType(sym) =>
- def toPrefix(pre: Type, clazz: Symbol): Type =
- if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) tp
- else if ((sym isNonBottomSubClass clazz) &&
- (pre.widen.typeSymbol isNonBottomSubClass sym)) {
- val pre1 = pre match {
- case SuperType(thistp, _) => thistp
- case _ => pre
- }
- if (!(pre1.isStable ||
- pre1.typeSymbol.isPackageClass ||
- pre1.typeSymbol.isModuleClass && pre1.typeSymbol.isStatic)) {
- stabilize(pre1, sym)
- } else {
- pre1
- }
- } else {
- toPrefix(base(pre, clazz).prefix, clazz.owner);
- }
- toPrefix(pre, clazz)
- case SingleType(pre, sym) =>
- if (sym.isPackageClass) tp // short path
- else {
- val pre1 = this(pre)
- if (pre1 eq pre) tp
- else if (pre1.isStable) singleType(pre1, sym)
- else pre1.memberType(sym).resultType //todo: this should be rolled into existential abstraction
- }
- // AM: Martin, is this description accurate?
- // walk the owner chain of `clazz` (the original argument to asSeenFrom) until we find the type param's owner (while rewriting pre as we crawl up the owner chain)
- // once we're at the owner, extract the information that pre encodes about the type param,
- // by minimally subsuming pre to the type instance of the class that owns the type param,
- // the type we're looking for is the type instance's type argument at the position corresponding to the type parameter
- // optimisation: skip this type parameter if it's not owned by a class, as those params are not influenced by the prefix through which they are seen
- // (concretely: type params of anonymous type functions, which currently can only arise from normalising type aliases, are owned by the type alias of which they are the eta-expansion)
- // (skolems also aren't affected: they are ruled out by the isTypeParameter check)
- case TypeRef(prefix, sym, args) if (sym.isTypeParameter && sym.owner.isClass) =>
- def toInstance(pre: Type, clazz: Symbol): Type =
- if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) mapOver(tp)
- //@M! see test pos/tcpoly_return_overriding.scala why mapOver is necessary
- else {
- def throwError = abort("" + tp + sym.locationString + " cannot be instantiated from " + pre.widen)
-
- def instParam(ps: List[Symbol], as: List[Type]): Type =
- if (ps.isEmpty) throwError
- else if (sym eq ps.head)
- // @M! don't just replace the whole thing, might be followed by type application
- appliedType(as.head, args mapConserve (this)) // @M: was as.head
- else instParam(ps.tail, as.tail);
- val symclazz = sym.owner
- if (symclazz == clazz && !pre.isInstanceOf[TypeVar] && (pre.widen.typeSymbol isNonBottomSubClass symclazz)) {
- // have to deconst because it may be a Class[T].
- pre.baseType(symclazz).deconst match {
- case TypeRef(_, basesym, baseargs) =>
- //Console.println("instantiating " + sym + " from " + basesym + " with " + basesym.typeParams + " and " + baseargs+", pre = "+pre+", symclazz = "+symclazz);//DEBUG
- if (sameLength(basesym.typeParams, baseargs)) {
- instParam(basesym.typeParams, baseargs)
- } else {
- throw new TypeError(
- "something is wrong (wrong class file?): "+basesym+
- " with type parameters "+
- basesym.typeParams.map(_.name).mkString("[",",","]")+
- " gets applied to arguments "+baseargs.mkString("[",",","]")+", phase = "+phase)
- }
- case ExistentialType(tparams, qtpe) =>
- capturedParams = capturedParams union tparams
- toInstance(qtpe, clazz)
- case _ =>
- throwError
- }
- } else toInstance(base(pre, clazz).prefix, clazz.owner)
- }
- toInstance(pre, clazz)
- case _ =>
- mapOver(tp)
- }
- }
-
- /** A base class to compute all substitutions */
- abstract class SubstMap[T](from: List[Symbol], to: List[T]) extends TypeMap {
- val fromContains = from.toSet // avoiding repeatedly traversing from
- assert(sameLength(from, to), "Unsound substitution from "+ from +" to "+ to)
-
- /** Are `sym' and `sym1' the same.
- * Can be tuned by subclasses.
- */
- protected def matches(sym: Symbol, sym1: Symbol): Boolean = sym eq sym1
-
- /** Map target to type, can be tuned by subclasses */
- protected def toType(fromtp: Type, tp: T): Type
-
- def subst(tp: Type, sym: Symbol, from: List[Symbol], to: List[T]): Type =
- if (from.isEmpty) tp
- // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(tp, from))
- else if (matches(from.head, sym)) toType(tp, to.head)
- else subst(tp, sym, from.tail, to.tail)
-
- protected def renameBoundSyms(tp: Type): Type = tp match {
- case MethodType(ps, restp) =>
- val ps1 = cloneSymbols(ps)
- copyMethodType(tp, ps1, renameBoundSyms(restp.substSym(ps, ps1)))
- case PolyType(bs, restp) =>
- val bs1 = cloneSymbols(bs)
- PolyType(bs1, renameBoundSyms(restp.substSym(bs, bs1)))
- case ExistentialType(bs, restp) =>
- val bs1 = cloneSymbols(bs)
- ExistentialType(bs1, restp.substSym(bs, bs1))
- case _ =>
- tp
- }
-
- def apply(tp0: Type): Type = if (from.isEmpty) tp0 else {
- val boundSyms = tp0.boundSyms
- val tp1 = if (boundSyms exists fromContains) renameBoundSyms(tp0) else tp0
- val tp = mapOver(tp1)
-
- tp match {
- // @M
- // 1) arguments must also be substituted (even when the "head" of the
- // applied type has already been substituted)
- // example: (subst RBound[RT] from [type RT,type RBound] to
- // [type RT&,type RBound&]) = RBound&[RT&]
- // 2) avoid loops (which occur because alpha-conversion is
- // not performed properly imo)
- // e.g. if in class Iterable[a] there is a new Iterable[(a,b)],
- // we must replace the a in Iterable[a] by (a,b)
- // (must not recurse --> loops)
- // 3) replacing m by List in m[Int] should yield List[Int], not just List
- case TypeRef(NoPrefix, sym, args) =>
- appliedType(subst(tp, sym, from, to), args) // if args.isEmpty, appliedType is the identity
- case SingleType(NoPrefix, sym) =>
- subst(tp, sym, from, to)
- case _ =>
- tp
- }
- }
- }
-
- /** A map to implement the `substSym' method. */
- class SubstSymMap(from: List[Symbol], to: List[Symbol]) extends SubstMap(from, to) {
- protected def toType(fromtp: Type, sym: Symbol) = fromtp match {
- case TypeRef(pre, _, args) => typeRef(pre, sym, args)
- case SingleType(pre, _) => singleType(pre, sym)
- }
- override def apply(tp: Type): Type = if (from.isEmpty) tp else {
- def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol =
- if (from.isEmpty) sym
- // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(sym, from))
- else if (matches(from.head, sym)) to.head
- else subst(sym, from.tail, to.tail)
- tp match {
- case TypeRef(pre, sym, args) if pre ne NoPrefix =>
- val newSym = subst(sym, from, to)
- // assert(newSym.typeParams.length == sym.typeParams.length, "typars mismatch in SubstSymMap: "+(sym, sym.typeParams, newSym, newSym.typeParams))
- mapOver(typeRef(pre, newSym, args)) // mapOver takes care of subst'ing in args
- case SingleType(pre, sym) if pre ne NoPrefix =>
- mapOver(singleType(pre, subst(sym, from, to)))
- case _ =>
- super.apply(tp)
- }
- }
-
-
- override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
- object trans extends TypeMapTransformer {
-
- def termMapsTo(sym: Symbol) =
- if (fromContains(sym))
- Some(to(from.indexOf(sym)))
- else
- None
-
- override def transform(tree: Tree) =
- tree match {
- case tree@Ident(_) =>
- termMapsTo(tree.symbol) match {
- case Some(tosym) =>
- if (tosym.info.bounds.hi.typeSymbol isSubClass SingletonClass) {
- Ident(tosym.existentialToString)
- .setSymbol(tosym)
- .setPos(tosym.pos)
- .setType(dropSingletonType(tosym.info.bounds.hi))
- } else {
- giveup()
- }
- case none => super.transform(tree)
- }
- case tree => super.transform(tree)
- }
- }
- trans.transform(tree)
- }
- }
-
- /** A map to implement the `subst' method. */
- class SubstTypeMap(from: List[Symbol], to: List[Type])
- extends SubstMap(from, to) {
- protected def toType(fromtp: Type, tp: Type) = tp
-
- override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
- object trans extends TypeMapTransformer {
- override def transform(tree: Tree) =
- tree match {
- case Ident(name) if fromContains(tree.symbol) =>
- val totpe = to(from.indexOf(tree.symbol))
- if (!totpe.isStable) giveup()
- else Ident(name).setPos(tree.pos).setSymbol(tree.symbol).setType(totpe)
-
- case _ => super.transform(tree)
- }
- }
- trans.transform(tree)
- }
-
- }
-
- /** A map to implement the `substThis' method. */
- class SubstThisMap(from: Symbol, to: Type) extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case ThisType(sym) if (sym == from) => to
- case _ => mapOver(tp)
- }
- }
-
- class SubstSuperMap(from: Type, to: Type) extends TypeMap {
- def apply(tp: Type): Type = if (tp eq from) to else mapOver(tp)
- }
-
- class SubstWildcardMap(from: List[Symbol]) extends TypeMap {
- def apply(tp: Type): Type = try {
- tp match {
- case TypeRef(_, sym, _) if from contains sym =>
- BoundedWildcardType(sym.info.bounds)
- case _ =>
- mapOver(tp)
- }
- } catch {
- case ex: MalformedType =>
- WildcardType
- }
- }
-
-// dependent method types
- object IsDependentCollector extends TypeCollector(false) {
- def traverse(tp: Type) {
- if(tp isImmediatelyDependent) result = true
- else if (!result) mapOver(tp)
- }
- }
-
- object ApproximateDependentMap extends TypeMap {
- def apply(tp: Type): Type =
- if(tp isImmediatelyDependent) WildcardType
- else mapOver(tp)
- }
-
- class InstantiateDependentMap(params: List[Symbol], actuals: List[Type]) extends TypeMap {
- private val actualsIndexed = actuals.toIndexedSeq
- override val dropNonConstraintAnnotations = true
-
- object ParamWithActual {
- def unapply(sym: Symbol): Option[Type] = {
- val pid = params indexOf sym
- if(pid != -1) Some(actualsIndexed(pid)) else None
- }
- }
-
- def apply(tp: Type): Type =
- mapOver(tp) match {
- case SingleType(NoPrefix, ParamWithActual(arg)) if arg.isStable => arg // unsound to replace args by unstable actual #3873
- // (soundly) expand type alias selections on implicit arguments, see depmet_implicit_oopsla* test cases -- typically, `param.isImplicit`
- case tp1@TypeRef(SingleType(NoPrefix, ParamWithActual(arg)), sym, targs) =>
- val res = typeRef(arg, sym, targs)
- if(res.typeSymbolDirect isAliasType) res.dealias
- else tp1
- case tp1 => tp1 // don't return the original `tp`, which may be different from `tp1`, due to `dropNonConstraintAnnotations`
- }
-
- def existentialsNeeded: List[Symbol] = existSyms.filter(_ ne null).toList
-
- private val existSyms: Array[Symbol] = new Array(actualsIndexed.size)
- private def haveExistential(i: Int) = {assert((i >= 0) && (i <= actualsIndexed.size)); existSyms(i) ne null}
-
- /* Return the type symbol for referencing a parameter inside the existential quantifier.
- * (Only needed if the actual is unstable.)
- */
- def existSymFor(actualIdx: Int) =
- if (haveExistential(actualIdx)) existSyms(actualIdx)
- else {
- val oldSym = params(actualIdx)
- val symowner = oldSym.owner
- val bound = singletonBounds(actualsIndexed(actualIdx))
-
- val sym = symowner.newExistential(oldSym.pos, newTypeName(oldSym.name + ".type"))
- sym.setInfo(bound)
- sym.setFlag(oldSym.flags)
-
- existSyms(actualIdx) = sym
- sym
- }
-
- //AM propagate more info to annotations -- this seems a bit ad-hoc... (based on code by spoon)
- override def mapOver(arg: Tree, giveup: ()=>Nothing): Tree = {
- object treeTrans extends Transformer {
- override def transform(tree: Tree): Tree = {
- tree match {
- case RefParamAt(pid) =>
- // TODO: this should be simplified; in the stable case, one can probably
- // just use an Ident to the tree.symbol. Why an existential in the non-stable case?
- val actual = actualsIndexed(pid)
- if (actual.isStable && actual.typeSymbol != NothingClass) {
- mkAttributedQualifier(actualsIndexed(pid), tree.symbol)
- } else {
- val sym = existSymFor(pid)
- (Ident(sym.name)
- copyAttrs tree
- setType typeRef(NoPrefix, sym, Nil))
- }
- case _ => super.transform(tree)
- }
- }
- object RefParamAt {
- def unapply(tree: Tree): Option[Int] = tree match {
- case Ident(_) => Some(params indexOf tree.symbol) filterNot (_ == -1)
- case _ => None
- }
- }
- }
-
- treeTrans.transform(arg)
- }
- }
-
-
- object StripAnnotationsMap extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case AnnotatedType(_, atp, _) =>
- mapOver(atp)
- case tp =>
- mapOver(tp)
- }
- }
-
- /** A map to convert every occurrence of a wildcard type to a fresh
- * type variable */
- object wildcardToTypeVarMap extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case WildcardType =>
- TypeVar(tp, new TypeConstraint)
- case BoundedWildcardType(bounds) =>
- TypeVar(tp, new TypeConstraint(List(bounds.lo), List(bounds.hi)))
- case _ =>
- mapOver(tp)
- }
- }
-
- /** A map to convert every occurrence of a type variable to a
- wildcard type */
- object typeVarToOriginMap extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case TypeVar(origin, _) => origin
- case _ => mapOver(tp)
- }
- }
-
- /** A map to implement the `contains' method */
- class ContainsCollector(sym: Symbol) extends TypeCollector(false) {
- def traverse(tp: Type) {
- if (!result) {
- tp.normalize match {
- case TypeRef(_, sym1, _) if (sym == sym1) => result = true
- case SingleType(_, sym1) if (sym == sym1) => result = true
- case _ => mapOver(tp)
- }
- }
- }
-
- override def mapOver(arg: Tree) = {
- for (t <- arg) {
- traverse(t.tpe)
- if (t.symbol == sym)
- result = true
- }
- Some(arg)
- }
- }
-
- /** A map to implement the `contains' method */
- class ContainsTypeCollector(t: Type) extends TypeCollector(false) {
- def traverse(tp: Type) {
- if (!result) {
- if (tp eq t) result = true
- else mapOver(tp)
- }
- }
- override def mapOver(arg: Tree) = {
- for (t <- arg) {
- traverse(t.tpe)
- }
- Some(arg)
- }
- }
-
- /** A map to implement the `filter' method */
- class FilterTypeCollector(p: Type => Boolean) extends TypeCollector(new ListBuffer[Type]) {
- def traverse(tp: Type) {
- if (p(tp)) result += tp
- mapOver(tp)
- }
- }
-
- class ForEachTypeTraverser(f: Type => Unit) extends TypeTraverser {
- def traverse(tp: Type) {
- f(tp)
- mapOver(tp)
- }
- }
-
- /** A map to implement the `filter' method */
- class FindTypeCollector(p: Type => Boolean) extends TypeCollector[Option[Type]](None) {
- def traverse(tp: Type) {
- if (result.isEmpty) {
- if (p(tp)) result = Some(tp)
- mapOver(tp)
- }
- }
- }
-
- /** A map to implement the `contains' method */
- object ErroneousCollector extends TypeCollector(false) {
- def traverse(tp: Type) {
- if (!result) {
- result = tp.isError
- mapOver(tp)
- }
- }
- }
-
- /** A map to compute the most deeply nested owner that contains all the symbols
- * of thistype or prefixless typerefs/singletype occurrences in given type.
- */
- object commonOwnerMap extends TypeMap {
- var result: Symbol = _
- def init() = { result = NoSymbol }
- def apply(tp: Type): Type = {
- assert(tp ne null)
- tp.normalize match {
- case ThisType(sym) =>
- register(sym)
- case TypeRef(NoPrefix, sym, args) =>
- register(sym.owner); args foreach apply
- case SingleType(NoPrefix, sym) =>
- register(sym.owner)
- case _ =>
- mapOver(tp)
- }
- tp
- }
- private def register(sym: Symbol) {
- while (result != NoSymbol && sym != result && !(sym isNestedIn result))
- result = result.owner;
- }
- }
-
- class MissingAliasControl extends ControlThrowable
- val missingAliasException = new MissingAliasControl
- class MissingTypeControl extends ControlThrowable
-
- object adaptToNewRunMap extends TypeMap {
- private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
- if (phase.flatClasses) {
- sym
- } else if (sym.isModuleClass) {
- adaptToNewRun(pre, sym.sourceModule).moduleClass
- } else if ((pre eq NoPrefix) || (pre eq NoType) || sym.isPackageClass) {
- sym
- } else {
- var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true)
- if (rebind0 == NoSymbol) {
- if (sym.isAliasType) throw missingAliasException
- if (settings.debug.value) println(pre+"."+sym+" does no longer exist, phase = "+phase)
- throw new MissingTypeControl // For build manager and presentation compiler purposes
- //assert(false, pre+"."+sym+" does no longer exist, phase = "+phase)
- }
- /** The two symbols have the same fully qualified name */
- def corresponds(sym1: Symbol, sym2: Symbol): Boolean =
- sym1.name == sym2.name && (sym1.isPackageClass || corresponds(sym1.owner, sym2.owner))
- if (!corresponds(sym.owner, rebind0.owner)) {
- if (settings.debug.value)
- log("ADAPT1 pre = "+pre+", sym = "+sym+sym.locationString+", rebind = "+rebind0+rebind0.locationString)
- val bcs = pre.baseClasses.dropWhile(bc => !corresponds(bc, sym.owner));
- if (bcs.isEmpty)
- assert(pre.typeSymbol.isRefinementClass, pre) // if pre is a refinementclass it might be a structural type => OK to leave it in.
- else
- rebind0 = pre.baseType(bcs.head).member(sym.name)
- if (settings.debug.value) log(
- "ADAPT2 pre = " + pre +
- ", bcs.head = " + bcs.head +
- ", sym = " + sym+sym.locationString +
- ", rebind = " + rebind0 + (
- if (rebind0 == NoSymbol) ""
- else rebind0.locationString
- )
- )
- }
- val rebind = rebind0.suchThat(sym => sym.isType || sym.isStable)
- if (rebind == NoSymbol) {
- if (settings.debug.value) log("" + phase + " " +phase.flatClasses+sym.owner+sym.name+" "+sym.isType)
- throw new MalformedType(pre, sym.nameString)
- }
- rebind
- }
- }
- def apply(tp: Type): Type = tp match {
- case ThisType(sym) =>
- try {
- val sym1 = adaptToNewRun(sym.owner.thisType, sym)
- if (sym1 == sym) tp else ThisType(sym1)
- } catch {
- case ex: MissingTypeControl =>
- tp
- }
- case SingleType(pre, sym) =>
- if (sym.isPackage) tp
- else {
- val pre1 = this(pre)
- val sym1 = adaptToNewRun(pre1, sym)
- if ((pre1 eq pre) && (sym1 eq sym)) tp
- else singleType(pre1, sym1)
- }
- case TypeRef(pre, sym, args) =>
- if (sym.isPackageClass) tp
- else {
- val pre1 = this(pre)
- val args1 = args mapConserve (this)
- try {
- val sym1 = adaptToNewRun(pre1, sym)
- if ((pre1 eq pre) && (sym1 eq sym) && (args1 eq args)/* && sym.isExternal*/) tp
- else typeRef(pre1, sym1, args1)
- } catch {
- case ex: MissingAliasControl =>
- apply(tp.dealias)
- case _: MissingTypeControl =>
- tp
- }
- }
- case MethodType(params, restp) =>
- val restp1 = this(restp)
- if (restp1 eq restp) tp
- else copyMethodType(tp, params, restp1)
- case NullaryMethodType(restp) =>
- val restp1 = this(restp)
- if (restp1 eq restp) tp
- else NullaryMethodType(restp1)
- case PolyType(tparams, restp) =>
- val restp1 = this(restp)
- if (restp1 eq restp) tp
- else PolyType(tparams, restp1)
-
- // Lukas: we need to check (together) whether we should also include parameter types
- // of PolyType and MethodType in adaptToNewRun
-
- case ClassInfoType(parents, decls, clazz) =>
- if (clazz.isPackageClass) tp
- else {
- val parents1 = parents mapConserve (this)
- if (parents1 eq parents) tp
- else ClassInfoType(parents1, decls, clazz)
- }
- case RefinedType(parents, decls) =>
- val parents1 = parents mapConserve (this)
- if (parents1 eq parents) tp
- else refinedType(parents1, tp.typeSymbol.owner, decls, tp.typeSymbol.owner.pos)
- case SuperType(_, _) => mapOver(tp)
- case TypeBounds(_, _) => mapOver(tp)
- case TypeVar(_, _) => mapOver(tp)
- case AnnotatedType(_,_,_) => mapOver(tp)
- case NotNullType(_) => mapOver(tp)
- case ExistentialType(_, _) => mapOver(tp)
- case _ => tp
- }
- }
-
- class SubTypePair(val tp1: Type, val tp2: Type) {
- override def hashCode = tp1.hashCode * 41 + tp2.hashCode
- override def equals(other: Any) = other match {
- case stp: SubTypePair =>
- (tp1 =:= stp.tp1) && (tp2 =:= stp.tp2)
- case _ =>
- false
- }
- override def toString = tp1+" <:<? "+tp2
- }
-
-// Helper Methods -------------------------------------------------------------
-
- final val LubGlbMargin = 0
-
- /** The maximum allowable depth of lubs or glbs over types `ts'
- * This is the maximum depth of all types in the base type sequences
- * of each of the types `ts', plus LubGlbMargin
- */
- def lubDepth(ts: List[Type]) = {
- var d = 0
- for (tp <- ts) d = math.max(d, tp.baseTypeSeqDepth)
- d + LubGlbMargin
- }
-
- /** Is intersection of given types populated? That is,
- * for all types tp1, tp2 in intersection
- * for all common base classes bc of tp1 and tp2
- * let bt1, bt2 be the base types of tp1, tp2 relative to class bc
- * Then:
- * bt1 and bt2 have the same prefix, and
- * any corresponding non-variant type arguments of bt1 and bt2 are the same
- */
- def isPopulated(tp1: Type, tp2: Type): Boolean = {
- def isConsistent(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
- case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
- assert(sym1 == sym2)
- pre1 =:= pre2 &&
- ((args1, args2, sym1.typeParams).zipped forall {
- (arg1, arg2, tparam) =>
- //if (tparam.variance == 0 && !(arg1 =:= arg2)) Console.println("inconsistent: "+arg1+"!="+arg2)//DEBUG
- if (tparam.variance == 0) arg1 =:= arg2
- else if (arg1.isInstanceOf[TypeVar])
- // if left-hand argument is a typevar, make it compatible with variance
- // this is for more precise pattern matching
- // todo: work this in the spec of this method
- // also: think what happens if there are embedded typevars?
- if (tparam.variance < 0) arg1 <:< arg2 else arg2 <:< arg1
- else true
- })
- case (et: ExistentialType, _) =>
- et.withTypeVars(isConsistent(_, tp2))
- case (_, et: ExistentialType) =>
- et.withTypeVars(isConsistent(tp1, _))
- }
-
- def check(tp1: Type, tp2: Type) =
- if (tp1.typeSymbol.isClass && tp1.typeSymbol.hasFlag(FINAL))
- tp1 <:< tp2 || isNumericValueClass(tp1.typeSymbol) && isNumericValueClass(tp2.typeSymbol)
- else tp1.baseClasses forall (bc =>
- tp2.baseTypeIndex(bc) < 0 || isConsistent(tp1.baseType(bc), tp2.baseType(bc)))
-
- check(tp1, tp2)/* && check(tp2, tp1)*/ // need to investgate why this can't be made symmetric -- neg/gadts1 fails, and run/existials also.
- }
-
- /** Does a pattern of type `patType' need an outer test when executed against
- * selector type `selType' in context defined by `currentOwner'?
- */
- def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = {
- def createDummyClone(pre: Type): Type = {
- val dummy = currentOwner.enclClass.newValue(NoPosition, nme.ANYNAME).setInfo(pre.widen)
- singleType(ThisType(currentOwner.enclClass), dummy)
- }
- def maybeCreateDummyClone(pre: Type, sym: Symbol): Type = pre match {
- case SingleType(pre1, sym1) =>
- if (sym1.isModule && sym1.isStatic) {
- NoType
- } else if (sym1.isModule && sym.owner == sym1.moduleClass) {
- val pre2 = maybeCreateDummyClone(pre1, sym1)
- if (pre2 eq NoType) pre2
- else singleType(pre2, sym1)
- } else {
- createDummyClone(pre)
- }
- case ThisType(clazz) =>
- if (clazz.isModuleClass)
- maybeCreateDummyClone(clazz.typeOfThis, sym)
- else if (sym.owner == clazz && (sym.hasFlag(PRIVATE) || sym.privateWithin == clazz))
- NoType
- else
- createDummyClone(pre)
- case _ =>
- NoType
- }
- patType match {
- case TypeRef(pre, sym, args) =>
- val pre1 = maybeCreateDummyClone(pre, sym)
- (pre1 ne NoType) && isPopulated(typeRef(pre1, sym, args), selType)
- case _ =>
- false
- }
- }
-
- private var subsametypeRecursions: Int = 0
-
- private def isUnifiable(pre1: Type, pre2: Type) =
- (beginsWithTypeVarOrIsRefined(pre1) || beginsWithTypeVarOrIsRefined(pre2)) && (pre1 =:= pre2)
-
- /** Returns true iff we are past phase specialize,
- * sym1 and sym2 are two existential skolems with equal names and bounds,
- * and pre1 and pre2 are equal prefixes
- */
- private def isSameSpecializedSkolem(sym1: Symbol, sym2: Symbol, pre1: Type, pre2: Type) = {
- sym1.isExistentialSkolem && sym2.isExistentialSkolem &&
- sym1.name == sym2.name &&
- phase.specialized &&
- sym1.info =:= sym2.info &&
- pre1 =:= pre2
- }
-
- private def equalSymsAndPrefixes(sym1: Symbol, pre1: Type, sym2: Symbol, pre2: Type): Boolean =
- if (sym1 == sym2) sym1.hasPackageFlag || phase.erasedTypes || pre1 =:= pre2
- else (sym1.name == sym2.name) && isUnifiable(pre1, pre2)
-
- /** Do `tp1' and `tp2' denote equivalent types?
- */
- def isSameType(tp1: Type, tp2: Type): Boolean = try {
- incCounter(sametypeCount)
- subsametypeRecursions += 1
- undoLog undoUnless {
- isSameType1(tp1, tp2)
- }
- } finally {
- subsametypeRecursions -= 1
- // XXX AM TODO: figure out when it is safe and needed to clear the log -- the commented approach below is too eager (it breaks #3281, #3866)
- // it doesn't help to keep separate recursion counts for the three methods that now share it
- // if (subsametypeRecursions == 0) undoLog.clear()
- }
-
- def isDifferentType(tp1: Type, tp2: Type): Boolean = try {
- subsametypeRecursions += 1
- undoLog undo { // undo type constraints that arise from operations in this block
- !isSameType1(tp1, tp2)
- }
- } finally {
- subsametypeRecursions -= 1
- // XXX AM TODO: figure out when it is safe and needed to clear the log -- the commented approach below is too eager (it breaks #3281, #3866)
- // it doesn't help to keep separate recursion counts for the three methods that now share it
- // if (subsametypeRecursions == 0) undoLog.clear()
- }
-
- def isDifferentTypeConstructor(tp1: Type, tp2: Type): Boolean = tp1 match {
- case TypeRef(pre1, sym1, _) =>
- tp2 match {
- case TypeRef(pre2, sym2, _) => sym1 != sym2 || isDifferentType(pre1, pre2)
- case _ => true
- }
- case _ => true
- }
-
- def normalizePlus(tp: Type) =
- if (isRawType(tp)) rawToExistential(tp)
- else tp.normalize
-
- /*
- todo: change to:
- def normalizePlus(tp: Type) = tp match {
- case TypeRef(pre, sym, List()) =>
- if (!sym.isInitialized) sym.rawInfo.load(sym)
- if (sym.isJavaDefined && !sym.typeParams.isEmpty) rawToExistential(tp)
- else tp.normalize
- case _ => tp.normalize
- }
- */
-/*
- private def isSameType0(tp1: Type, tp2: Type): Boolean = {
- if (tp1 eq tp2) return true
- ((tp1, tp2) match {
- case (ErrorType, _) => true
- case (WildcardType, _) => true
- case (_, ErrorType) => true
- case (_, WildcardType) => true
-
- case (NoType, _) => false
- case (NoPrefix, _) => tp2.typeSymbol.isPackageClass
- case (_, NoType) => false
- case (_, NoPrefix) => tp1.typeSymbol.isPackageClass
-
- case (ThisType(sym1), ThisType(sym2))
- if (sym1 == sym2) =>
- true
- case (SingleType(pre1, sym1), SingleType(pre2, sym2))
- if (equalSymsAndPrefixes(sym1, pre1, sym2, pre2)) =>
- true
-/*
- case (SingleType(pre1, sym1), ThisType(sym2))
- if (sym1.isModule &&
- sym1.moduleClass == sym2 &&
- pre1 =:= sym2.owner.thisType) =>
- true
- case (ThisType(sym1), SingleType(pre2, sym2))
- if (sym2.isModule &&
- sym2.moduleClass == sym1 &&
- pre2 =:= sym1.owner.thisType) =>
- true
-*/
- case (ConstantType(value1), ConstantType(value2)) =>
- value1 == value2
- case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
- equalSymsAndPrefixes(sym1, pre1, sym2, pre2) &&
- ((tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) ||
- isSameTypes(args1, args2))
- // @M! normalize reduces higher-kinded case to PolyType's
- case (RefinedType(parents1, ref1), RefinedType(parents2, ref2)) =>
- def isSubScope(s1: Scope, s2: Scope): Boolean = s2.toList.forall {
- sym2 =>
- var e1 = s1.lookupEntry(sym2.name)
- (e1 ne null) && {
- val substSym = sym2.info.substThis(sym2.owner, e1.sym.owner.thisType)
- var isEqual = false
- while (!isEqual && (e1 ne null)) {
- isEqual = e1.sym.info =:= substSym
- e1 = s1.lookupNextEntry(e1)
- }
- isEqual
- }
- }
- //Console.println("is same? " + tp1 + " " + tp2 + " " + tp1.typeSymbol.owner + " " + tp2.typeSymbol.owner)//DEBUG
- isSameTypes(parents1, parents2) && isSubScope(ref1, ref2) && isSubScope(ref2, ref1)
- case (MethodType(params1, res1), MethodType(params2, res2)) =>
- // new dependent types: probably fix this, use substSym as done for PolyType
- (isSameTypes(tp1.paramTypes, tp2.paramTypes) &&
- res1 =:= res2 &&
- tp1.isImplicit == tp2.isImplicit)
- case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
- // assert((tparams1 map (_.typeParams.length)) == (tparams2 map (_.typeParams.length)))
- (tparams1.length == tparams2.length) && (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) && // @M looks like it might suffer from same problem as #2210
- res1 =:= res2.substSym(tparams2, tparams1)
- case (ExistentialType(tparams1, res1), ExistentialType(tparams2, res2)) =>
- (tparams1.length == tparams2.length) && (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) && // @M looks like it might suffer from same problem as #2210
- res1 =:= res2.substSym(tparams2, tparams1)
- case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) =>
- lo1 =:= lo2 && hi1 =:= hi2
- case (BoundedWildcardType(bounds), _) =>
- bounds containsType tp2
- case (_, BoundedWildcardType(bounds)) =>
- bounds containsType tp1
- case (tv @ TypeVar(_,_), tp) =>
- tv.registerTypeEquality(tp, true)
- case (tp, tv @ TypeVar(_,_)) =>
- tv.registerTypeEquality(tp, false)
- case (AnnotatedType(_,_,_), _) =>
- annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
- case (_, AnnotatedType(_,_,_)) =>
- annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
- case (_: SingletonType, _: SingletonType) =>
- var origin1 = tp1
- while (origin1.underlying.isInstanceOf[SingletonType]) {
- assert(origin1 ne origin1.underlying, origin1)
- origin1 = origin1.underlying
- }
- var origin2 = tp2
- while (origin2.underlying.isInstanceOf[SingletonType]) {
- assert(origin2 ne origin2.underlying, origin2)
- origin2 = origin2.underlying
- }
- ((origin1 ne tp1) || (origin2 ne tp2)) && (origin1 =:= origin2)
- case _ =>
- false
- }) || {
- val tp1n = normalizePlus(tp1)
- val tp2n = normalizePlus(tp2)
- ((tp1n ne tp1) || (tp2n ne tp2)) && isSameType(tp1n, tp2n)
- }
- }
-*/
- private def isSameType1(tp1: Type, tp2: Type): Boolean = {
- if ((tp1 eq tp2) ||
- (tp1 eq ErrorType) || (tp1 eq WildcardType) ||
- (tp2 eq ErrorType) || (tp2 eq WildcardType))
- true
- else if ((tp1 eq NoType) || (tp2 eq NoType))
- false
- else if (tp1 eq NoPrefix)
- tp2.typeSymbol.isPackageClass
- else if (tp2 eq NoPrefix)
- tp1.typeSymbol.isPackageClass
- else {
- isSameType2(tp1, tp2) || {
- val tp1n = normalizePlus(tp1)
- val tp2n = normalizePlus(tp2)
- ((tp1n ne tp1) || (tp2n ne tp2)) && isSameType(tp1n, tp2n)
- }
- }
- }
-
- def isSameType2(tp1: Type, tp2: Type): Boolean = {
- tp1 match {
- case tr1: TypeRef =>
- tp2 match {
- case tr2: TypeRef =>
- return (equalSymsAndPrefixes(tr1.sym, tr1.pre, tr2.sym, tr2.pre) &&
- ((tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) ||
- isSameTypes(tr1.args, tr2.args))) ||
- ((tr1.pre, tr2.pre) match {
- case (tv @ TypeVar(_,_), _) => tv.registerTypeSelection(tr1.sym, tr2)
- case (_, tv @ TypeVar(_,_)) => tv.registerTypeSelection(tr2.sym, tr1)
- case _ => false
- })
- case _ =>
- }
- case tt1: ThisType =>
- tp2 match {
- case tt2: ThisType =>
- if (tt1.sym == tt2.sym) return true
- case _ =>
- }
- case st1: SingleType =>
- tp2 match {
- case st2: SingleType =>
- if (equalSymsAndPrefixes(st1.sym, st1.pre, st2.sym, st2.pre)) return true
- case _ =>
- }
- case ct1: ConstantType =>
- tp2 match {
- case ct2: ConstantType =>
- return (ct1.value == ct2.value)
- case _ =>
- }
- case rt1: RefinedType =>
- tp2 match {
- case rt2: RefinedType => //
- def isSubScope(s1: Scope, s2: Scope): Boolean = s2.toList.forall {
- sym2 =>
- var e1 = s1.lookupEntry(sym2.name)
- (e1 ne null) && {
- val substSym = sym2.info.substThis(sym2.owner, e1.sym.owner.thisType)
- var isEqual = false
- while (!isEqual && (e1 ne null)) {
- isEqual = e1.sym.info =:= substSym
- e1 = s1.lookupNextEntry(e1)
- }
- isEqual
- }
- }
- //Console.println("is same? " + tp1 + " " + tp2 + " " + tp1.typeSymbol.owner + " " + tp2.typeSymbol.owner)//DEBUG
- return isSameTypes(rt1.parents, rt2.parents) && {
- val decls1 = rt1.decls
- val decls2 = rt2.decls
- isSubScope(decls1, decls2) && isSubScope(decls2, decls1)
- }
- case _ =>
- }
- case mt1: MethodType =>
- tp2 match {
- case mt2: MethodType =>
- // DEPMETTODO new dependent types: probably fix this, use substSym as done for PolyType
- return isSameTypes(mt1.paramTypes, mt2.paramTypes) &&
- mt1.resultType =:= mt2.resultType &&
- mt1.isImplicit == mt2.isImplicit
- // note: no case NullaryMethodType(restpe) => return mt1.params.isEmpty && mt1.resultType =:= restpe
- case _ =>
- }
- case NullaryMethodType(restpe1) =>
- tp2 match {
- // note: no case mt2: MethodType => return mt2.params.isEmpty && restpe =:= mt2.resultType
- case NullaryMethodType(restpe2) =>
- return restpe1 =:= restpe2
- case _ =>
- }
- case PolyType(tparams1, res1) =>
- tp2 match {
- case PolyType(tparams2, res2) =>
-// assert((tparams1 map (_.typeParams.length)) == (tparams2 map (_.typeParams.length)))
- // @M looks like it might suffer from same problem as #2210
- return (
- (sameLength(tparams1, tparams2)) && // corresponds does not check length of two sequences before checking the predicate
- (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) &&
- res1 =:= res2.substSym(tparams2, tparams1)
- )
- case _ =>
- }
- case ExistentialType(tparams1, res1) =>
- tp2 match {
- case ExistentialType(tparams2, res2) =>
- // @M looks like it might suffer from same problem as #2210
- return (
- // corresponds does not check length of two sequences before checking the predicate -- faster & needed to avoid crasher in #2956
- sameLength(tparams1, tparams2) &&
- (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) &&
- res1 =:= res2.substSym(tparams2, tparams1)
- )
- case _ =>
- }
- case TypeBounds(lo1, hi1) =>
- tp2 match {
- case TypeBounds(lo2, hi2) =>
- return lo1 =:= lo2 && hi1 =:= hi2
- case _ =>
- }
- case BoundedWildcardType(bounds) =>
- return bounds containsType tp2
- case _ =>
- }
- tp2 match {
- case BoundedWildcardType(bounds) =>
- return bounds containsType tp1
- case _ =>
- }
- tp1 match {
- case tv @ TypeVar(_,_) =>
- return tv.registerTypeEquality(tp2, true)
- case _ =>
- }
- tp2 match {
- case tv @ TypeVar(_,_) =>
- return tv.registerTypeEquality(tp1, false)
- case _ =>
- }
- tp1 match {
- case _: AnnotatedType =>
- return annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
- case _ =>
- }
- tp2 match {
- case _: AnnotatedType =>
- return annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
- case _ =>
- }
- tp1 match {
- case _: SingletonType =>
- tp2 match {
- case _: SingletonType =>
- @inline def chaseDealiasedUnderlying(tp: Type): Type = {
- var origin = tp
- var next = origin.underlying.dealias
- while (next.isInstanceOf[SingletonType]) {
- assert(origin ne next, origin)
- origin = next
- next = origin.underlying.dealias
- }
- origin
- }
- val origin1 = chaseDealiasedUnderlying(tp1)
- val origin2 = chaseDealiasedUnderlying(tp2)
- ((origin1 ne tp1) || (origin2 ne tp2)) && (origin1 =:= origin2)
- case _ =>
- false
- }
- case _ =>
- false
- }
- }
-
- /** Are `tps1' and `tps2' lists of pairwise equivalent
- * types?
- */
- def isSameTypes(tps1: List[Type], tps2: List[Type]): Boolean = (tps1 corresponds tps2)(_ =:= _)
-
- /** True if two lists have the same length. Since calling length on linear sequences
- * is O(n), it is an inadvisable way to test length equality.
- */
- final def sameLength(xs1: List[_], xs2: List[_]) = compareLengths(xs1, xs2) == 0
- @tailrec final def compareLengths(xs1: List[_], xs2: List[_]): Int =
- if (xs1.isEmpty) { if (xs2.isEmpty) 0 else -1 }
- else if (xs2.isEmpty) 1
- else compareLengths(xs1.tail, xs2.tail)
-
- /** Again avoiding calling length, but the lengthCompare interface is clunky.
- */
- final def hasLength(xs: List[_], len: Int) = xs.lengthCompare(len) == 0
-
- private val pendingSubTypes = new mutable.HashSet[SubTypePair]
- private var basetypeRecursions: Int = 0
- private val pendingBaseTypes = new mutable.HashSet[Type]
-
- def isSubType(tp1: Type, tp2: Type): Boolean = isSubType(tp1, tp2, AnyDepth)
-
- def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean = try {
- subsametypeRecursions += 1
-
- undoLog undoUnless { // if subtype test fails, it should not affect constraints on typevars
- if (subsametypeRecursions >= LogPendingSubTypesThreshold) {
- val p = new SubTypePair(tp1, tp2)
- if (pendingSubTypes(p))
- false
- else
- try {
- pendingSubTypes += p
- isSubType2(tp1, tp2, depth)
- } finally {
- pendingSubTypes -= p
- }
- } else {
- isSubType2(tp1, tp2, depth)
- }
- }
- } finally {
- subsametypeRecursions -= 1
- // XXX AM TODO: figure out when it is safe and needed to clear the log -- the commented approach below is too eager (it breaks #3281, #3866)
- // it doesn't help to keep separate recursion counts for the three methods that now share it
- // if (subsametypeRecursions == 0) undoLog.clear()
- }
-
- /** Does this type have a prefix that begins with a type variable,
- * or is it a refinement type? For type prefixes that fulfil this condition,
- * type selections with the same name of equal (wrt) =:= prefixes are
- * considered equal wrt =:=
- */
- def beginsWithTypeVarOrIsRefined(tp: Type): Boolean = tp match {
- case SingleType(pre, sym) =>
- !(sym hasFlag PACKAGE) && beginsWithTypeVarOrIsRefined(pre)
- case tv@TypeVar(_, constr) =>
- !tv.instValid || beginsWithTypeVarOrIsRefined(constr.inst)
- case RefinedType(_, _) =>
- true
- case _ =>
- false
- }
-
- def instTypeVar(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) =>
- typeRef(instTypeVar(pre), sym, args)
- case SingleType(pre, sym) =>
- singleType(instTypeVar(pre), sym)
- case TypeVar(_, constr) =>
- instTypeVar(constr.inst)
- case _ =>
- tp
- }
-
- def isErrorOrWildcard(tp: Type) = (tp eq ErrorType) || (tp eq WildcardType)
-
- def isSingleType(tp: Type) = tp match {
- case ThisType(_) | SuperType(_, _) | SingleType(_, _) => true
- case _ => false
- }
-
- def isConstantType(tp: Type) = tp match {
- case ConstantType(_) => true
- case _ => false
- }
-
- // @assume tp1.isHigherKinded || tp2.isHigherKinded
- def isHKSubType0(tp1: Type, tp2: Type, depth: Int): Boolean = (
- tp1.typeSymbol == NothingClass
- ||
- tp2.typeSymbol == AnyClass // @M Any and Nothing are super-type resp. subtype of every well-kinded type
- || // @M! normalize reduces higher-kinded case to PolyType's
- ((tp1.normalize.withoutAnnotations , tp2.normalize.withoutAnnotations) match {
- case (PolyType(tparams1, res1), PolyType(tparams2, res2)) => // @assume tp1.isHigherKinded && tp2.isHigherKinded (as they were both normalized to PolyType)
- sameLength(tparams1, tparams2) && {
- if (tparams1.head.owner.isMethod) { // fast-path: polymorphic method type -- type params cannot be captured
- (tparams1 corresponds tparams2)((p1, p2) => p2.info.substSym(tparams2, tparams1) <:< p1.info) &&
- res1 <:< res2.substSym(tparams2, tparams1)
- } else { // normalized higher-kinded type
- //@M for an example of why we need to generate fresh symbols, see neg/tcpoly_ticket2101.scala
- val tpsFresh = cloneSymbols(tparams1)
-
- (tparams1 corresponds tparams2)((p1, p2) =>
- p2.info.substSym(tparams2, tpsFresh) <:< p1.info.substSym(tparams1, tpsFresh)) &&
- res1.substSym(tparams1, tpsFresh) <:< res2.substSym(tparams2, tpsFresh)
-
- //@M the forall in the previous test could be optimised to the following,
- // but not worth the extra complexity since it only shaves 1s from quick.comp
- // (List.forall2(tpsFresh/*optimisation*/, tparams2)((p1, p2) =>
- // p2.info.substSym(tparams2, tpsFresh) <:< p1.info /*optimisation, == (p1 from tparams1).info.substSym(tparams1, tpsFresh)*/) &&
- // this optimisation holds because inlining cloneSymbols in `val tpsFresh = cloneSymbols(tparams1)` gives:
- // val tpsFresh = tparams1 map (_.cloneSymbol)
- // for (tpFresh <- tpsFresh) tpFresh.setInfo(tpFresh.info.substSym(tparams1, tpsFresh))
- }
- } && annotationsConform(tp1.normalize, tp2.normalize)
- case (_, _) => false // @assume !tp1.isHigherKinded || !tp2.isHigherKinded
- // --> thus, cannot be subtypes (Any/Nothing has already been checked)
- }))
-
- /** True if all three arguments have the same number of elements and
- * the function is true for all the triples.
- */
- @tailrec final def corresponds3[A, B, C](xs1: List[A], xs2: List[B], xs3: List[C], f: (A, B, C) => Boolean): Boolean = {
- if (xs1.isEmpty) xs2.isEmpty && xs3.isEmpty
- else !xs2.isEmpty && !xs3.isEmpty && f(xs1.head, xs2.head, xs3.head) && corresponds3(xs1.tail, xs2.tail, xs3.tail, f)
- }
-
- def isSubArg(t1: Type, t2: Type, variance: Int) =
- (variance > 0 || t2 <:< t1) && (variance < 0 || t1 <:< t2)
-
- def isSubArgs(tps1: List[Type], tps2: List[Type], tparams: List[Symbol]): Boolean =
- corresponds3(tps1, tps2, tparams map (_.variance), isSubArg)
-
- def differentOrNone(tp1: Type, tp2: Type) = if (tp1 eq tp2) NoType else tp1
-
- /** Does type `tp1' conform to `tp2'?
- */
- private def isSubType2(tp1: Type, tp2: Type, depth: Int): Boolean = {
- if ((tp1 eq tp2) || isErrorOrWildcard(tp1) || isErrorOrWildcard(tp2)) return true
- if ((tp1 eq NoType) || (tp2 eq NoType)) return false
- if (tp1 eq NoPrefix) return (tp2 eq NoPrefix) || tp2.typeSymbol.isPackageClass
- if (tp2 eq NoPrefix) return tp1.typeSymbol.isPackageClass
- if (isSingleType(tp1) && isSingleType(tp2) || isConstantType(tp1) && isConstantType(tp2)) return tp1 =:= tp2
- if (tp1.isHigherKinded || tp2.isHigherKinded) return isHKSubType0(tp1, tp2, depth)
-
- /** First try, on the right:
- * - unwrap Annotated types, BoundedWildcardTypes,
- * - bind TypeVars on the right, if lhs is not Annotated nor BoundedWildcard
- * - handle common cases for first-kind TypeRefs on both sides as a fast path.
- */
- def firstTry = { incCounter(ctr1); tp2 match {
- // fast path: two typerefs, none of them HK
- case tr2: TypeRef =>
- tp1 match {
- case tr1: TypeRef =>
- val sym1 = tr1.sym
- val sym2 = tr2.sym
- val pre1 = tr1.pre
- val pre2 = tr2.pre
- (((if (sym1 == sym2) phase.erasedTypes || pre1 <:< pre2
- else (sym1.name == sym2.name && !sym1.isModuleClass && !sym2.isModuleClass &&
- (isUnifiable(pre1, pre2) || isSameSpecializedSkolem(sym1, sym2, pre1, pre2)))) &&
- isSubArgs(tr1.args, tr2.args, sym1.typeParams))
- ||
- sym2.isClass && {
- val base = tr1 baseType sym2
- (base ne tr1) && base <:< tr2
- }
- ||
- thirdTryRef(tr1, tr2))
- case _ =>
- secondTry
- }
- case AnnotatedType(_, _, _) =>
- tp1.withoutAnnotations <:< tp2.withoutAnnotations && annotationsConform(tp1, tp2)
- case BoundedWildcardType(bounds) =>
- tp1 <:< bounds.hi
- case tv2 @ TypeVar(_, constr2) =>
- tp1 match {
- case AnnotatedType(_, _, _) | BoundedWildcardType(_) =>
- secondTry
- case _ =>
- tv2.registerBound(tp1, true)
- }
- case _ =>
- secondTry
- }}
-
- /** Second try, on the left:
- * - unwrap AnnotatedTypes, BoundedWildcardTypes,
- * - bind typevars,
- * - handle existential types by skolemization.
- */
- def secondTry = { incCounter(ctr2); tp1 match {
- case AnnotatedType(_, _, _) =>
- tp1.withoutAnnotations <:< tp2.withoutAnnotations && annotationsConform(tp1, tp2)
- case BoundedWildcardType(bounds) =>
- tp1.bounds.lo <:< tp2
- case tv @ TypeVar(_,_) =>
- tv.registerBound(tp2, false)
- case ExistentialType(_, _) =>
- try {
- skolemizationLevel += 1
- tp1.skolemizeExistential <:< tp2
- } finally {
- skolemizationLevel -= 1
- }
- case _ =>
- thirdTry
- }}
-
- def thirdTryRef(tp1: Type, tp2: TypeRef): Boolean = {
- incCounter(ctr3);
- val sym2 = tp2.sym
- sym2 match {
- case NotNullClass => tp1.isNotNull
- case SingletonClass => tp1.isStable || fourthTry
- case _: ClassSymbol =>
- if (isRaw(sym2, tp2.args))
- isSubType(tp1, rawToExistential(tp2), depth)
- else if (sym2.name == tpnme.REFINE_CLASS_NAME)
- isSubType(tp1, sym2.info, depth)
- else
- fourthTry
- case _: TypeSymbol =>
- if (sym2 hasFlag DEFERRED) {
- val tp2a = tp2.bounds.lo
- isDifferentTypeConstructor(tp2, tp2a) && tp1 <:< tp2a || fourthTry
- } else {
- isSubType(tp1.normalize, tp2.normalize, depth)
- }
- case _ =>
- fourthTry
- }
- }
-
- /** Third try, on the right:
- * - decompose refined types.
- * - handle typerefs, existentials, and notnull types.
- * - handle left+right method types, polytypes, typebounds
- */
- def thirdTry = { incCounter(ctr3); tp2 match {
- case tr2: TypeRef =>
- thirdTryRef(tp1, tr2)
- case rt2: RefinedType =>
- (rt2.parents forall (tp1 <:< _)) &&
- (rt2.decls.toList forall tp1.specializes)
- case et2: ExistentialType =>
- et2.withTypeVars(tp1 <:< _, depth) || fourthTry
- case nn2: NotNullType =>
- tp1.isNotNull && tp1 <:< nn2.underlying
- case mt2: MethodType =>
- tp1 match {
- case mt1 @ MethodType(params1, res1) =>
- val params2 = mt2.params
- val res2 = mt2.resultType
- (sameLength(params1, params2) &&
- matchingParams(params1, params2, mt1.isJava, mt2.isJava) &&
- (res1 <:< res2) &&
- mt1.isImplicit == mt2.isImplicit)
- // TODO: if mt1.params.isEmpty, consider NullaryMethodType?
- case _ =>
- false
- }
- case pt2 @ NullaryMethodType(_) =>
- tp1 match {
- // TODO: consider MethodType mt for which mt.params.isEmpty??
- case pt1 @ NullaryMethodType(_) =>
- pt1.resultType <:< pt2.resultType
- case _ =>
- false
- }
- case TypeBounds(lo2, hi2) =>
- tp1 match {
- case TypeBounds(lo1, hi1) =>
- lo2 <:< lo1 && hi1 <:< hi2
- case _ =>
- false
- }
- case _ =>
- fourthTry
- }}
-
- /** Fourth try, on the left:
- * - handle typerefs, refined types, notnull and singleton types.
- */
- def fourthTry = { incCounter(ctr4); tp1 match {
- case tr1 @ TypeRef(_, sym1, _) =>
- sym1 match {
- case NothingClass => true
- case NullClass =>
- tp2 match {
- case TypeRef(_, sym2, _) =>
- sym2.isClass && (sym2 isNonBottomSubClass ObjectClass) &&
- !(tp2.normalize.typeSymbol isNonBottomSubClass NotNullClass)
- case _ =>
- isSingleType(tp2) && tp1 <:< tp2.widen
- }
- case _: ClassSymbol =>
- if (isRaw(sym1, tr1.args))
- isSubType(rawToExistential(tp1), tp2, depth)
- else
- sym1.name == tpnme.REFINE_CLASS_NAME &&
- isSubType(sym1.info, tp2, depth)
- case _: TypeSymbol =>
- if (sym1 hasFlag DEFERRED) {
- val tp1a = tp1.bounds.hi
- isDifferentTypeConstructor(tp1, tp1a) && tp1a <:< tp2
- } else {
- isSubType(tp1.normalize, tp2.normalize, depth)
- }
- case _ =>
- false
- }
- case RefinedType(parents1, _) =>
- parents1 exists (_ <:< tp2)
- case _: SingletonType | _: NotNullType =>
- tp1.underlying <:< tp2
- case _ =>
- false
- }}
-
- firstTry
- }
-
- /** Are `tps1' and `tps2' lists of equal length such
- * that all elements of `tps1' conform to corresponding elements
- * of `tps2'?
- */
- def isSubTypes(tps1: List[Type], tps2: List[Type]): Boolean = (tps1 corresponds tps2)(_ <:< _)
-
- /** Does type `tp' implement symbol `sym' with same or
- * stronger type? Exact only if `sym' is a member of some
- * refinement type, otherwise we might return false negatives.
- */
- def specializesSym(tp: Type, sym: Symbol): Boolean =
- tp.typeSymbol == NothingClass ||
- tp.typeSymbol == NullClass && (sym.owner isSubClass ObjectClass) ||
- (tp.nonPrivateMember(sym.name).alternatives exists
- (alt => sym == alt || specializesSym(tp.narrow, alt, sym.owner.thisType, sym)))
-
- /** Does member `sym1' of `tp1' have a stronger type
- * than member `sym2' of `tp2'?
- */
- private def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol): Boolean = {
- val info1 = tp1.memberInfo(sym1)
- val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1)
- //System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG
- sym2.isTerm && (info1 <:< info2) /*&& (!sym2.isStable || sym1.isStable) */ ||
- sym2.isAbstractType && {
- val memberTp1 = tp1.memberType(sym1)
- // println("kinds conform? "+(memberTp1, tp1, sym2, kindsConform(List(sym2), List(memberTp1), tp2, sym2.owner)))
- info2.bounds.containsType(memberTp1) &&
- kindsConform(List(sym2), List(memberTp1), tp1, sym1.owner)
- } ||
- sym2.isAliasType && tp2.memberType(sym2).substThis(tp2.typeSymbol, tp1) =:= tp1.memberType(sym1) //@MAT ok
- }
-
- /** A function implementing `tp1' matches `tp2' */
- final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
- def matchesQuantified(tparams1: List[Symbol], tparams2: List[Symbol], res1: Type, res2: Type): Boolean = (
- sameLength(tparams1, tparams2) &&
- matchesType(res1, res2.substSym(tparams2, tparams1), alwaysMatchSimple)
- )
- def lastTry =
- tp2 match {
- case ExistentialType(_, res2) if alwaysMatchSimple =>
- matchesType(tp1, res2, true)
- case MethodType(_, _) =>
- false
- case PolyType(tparams2, res2) =>
- tparams2.isEmpty && matchesType(tp1, res2, alwaysMatchSimple)
- case _ =>
- alwaysMatchSimple || tp1 =:= tp2
- }
- tp1 match {
- case mt1 @ MethodType(params1, res1) =>
- tp2 match {
- case mt2 @ MethodType(params2, res2) =>
- sameLength(params1, params2) && // useful pre-screening optimization
- matchingParams(params1, params2, mt1.isJava, mt2.isJava) &&
- matchesType(res1, res2, alwaysMatchSimple) &&
- mt1.isImplicit == mt2.isImplicit
- case NullaryMethodType(res2) =>
- if (params1.isEmpty) matchesType(res1, res2, alwaysMatchSimple)
- else matchesType(tp1, res2, alwaysMatchSimple)
- case ExistentialType(_, res2) =>
- alwaysMatchSimple && matchesType(tp1, res2, true)
- case _ =>
- false
- }
- case mt1 @ NullaryMethodType(res1) =>
- tp2 match {
- case mt2 @ MethodType(Nil, res2) => // could never match if params nonEmpty, and !mt2.isImplicit is implied by empty param list
- matchesType(res1, res2, alwaysMatchSimple)
- case NullaryMethodType(res2) =>
- matchesType(res1, res2, alwaysMatchSimple)
- case ExistentialType(_, res2) =>
- alwaysMatchSimple && matchesType(tp1, res2, true)
- case _ =>
- matchesType(res1, tp2, alwaysMatchSimple)
- }
- case PolyType(tparams1, res1) =>
- tp2 match {
- case PolyType(tparams2, res2) =>
- matchesQuantified(tparams1, tparams2, res1, res2)
- case ExistentialType(_, res2) =>
- alwaysMatchSimple && matchesType(tp1, res2, true)
- case _ =>
- false // remember that tparams1.nonEmpty is now an invariant of PolyType
- }
- case ExistentialType(tparams1, res1) =>
- tp2 match {
- case ExistentialType(tparams2, res2) =>
- matchesQuantified(tparams1, tparams2, res1, res2)
- case _ =>
- if (alwaysMatchSimple) matchesType(res1, tp2, true)
- else lastTry
- }
- case _ =>
- lastTry
- }
- }
-
-/** matchesType above is an optimized version of the following implementation:
-
- def matchesType2(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
- def matchesQuantified(tparams1: List[Symbol], tparams2: List[Symbol], res1: Type, res2: Type): Boolean =
- tparams1.length == tparams2.length &&
- matchesType(res1, res2.substSym(tparams2, tparams1), alwaysMatchSimple)
- (tp1, tp2) match {
- case (MethodType(params1, res1), MethodType(params2, res2)) =>
- params1.length == params2.length && // useful pre-secreening optimization
- matchingParams(params1, params2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
- matchesType(res1, res2, alwaysMatchSimple) &&
- tp1.isImplicit == tp2.isImplicit
- case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
- matchesQuantified(tparams1, tparams2, res1, res2)
- case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) =>
- matchesType(rtp1, rtp2, alwaysMatchSimple)
- case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) =>
- matchesType(rtp1, rtp2, alwaysMatchSimple)
- case (ExistentialType(tparams1, res1), ExistentialType(tparams2, res2)) =>
- matchesQuantified(tparams1, tparams2, res1, res2)
- case (ExistentialType(_, res1), _) if alwaysMatchSimple =>
- matchesType(res1, tp2, alwaysMatchSimple)
- case (_, ExistentialType(_, res2)) if alwaysMatchSimple =>
- matchesType(tp1, res2, alwaysMatchSimple)
- case (NullaryMethodType(rtp1), _) =>
- matchesType(rtp1, tp2, alwaysMatchSimple)
- case (_, NullaryMethodType(rtp2)) =>
- matchesType(tp1, rtp2, alwaysMatchSimple)
- case (MethodType(_, _), _) => false
- case (PolyType(_, _), _) => false
- case (_, MethodType(_, _)) => false
- case (_, PolyType(_, _)) => false
- case _ =>
- alwaysMatchSimple || tp1 =:= tp2
- }
- }
-*/
-
- /** Are `syms1' and `syms2' parameter lists with pairwise equivalent types? */
- private def matchingParams(syms1: List[Symbol], syms2: List[Symbol], syms1isJava: Boolean, syms2isJava: Boolean): Boolean = syms1 match {
- case Nil =>
- syms2.isEmpty
- case sym1 :: rest1 =>
- syms2 match {
- case Nil =>
- false
- case sym2 :: rest2 =>
- val tp1 = sym1.tpe
- val tp2 = sym2.tpe
- (tp1 =:= tp2 ||
- syms1isJava && tp2.typeSymbol == ObjectClass && tp1.typeSymbol == AnyClass ||
- syms2isJava && tp1.typeSymbol == ObjectClass && tp2.typeSymbol == AnyClass) &&
- matchingParams(rest1, rest2, syms1isJava, syms2isJava)
- }
- }
-
- /** like map2, but returns list `xs' itself - instead of a copy - if function
- * `f' maps all elements to themselves.
- */
- def map2Conserve[A <: AnyRef, B](xs: List[A], ys: List[B])(f: (A, B) => A): List[A] =
- if (xs.isEmpty) xs
- else {
- val x1 = f(xs.head, ys.head)
- val xs1 = map2Conserve(xs.tail, ys.tail)(f)
- if ((x1 eq xs.head) && (xs1 eq xs.tail)) xs
- else x1 :: xs1
- }
-
- /** Solve constraint collected in types `tvars'.
- *
- * @param tvars All type variables to be instantiated.
- * @param tparams The type parameters corresponding to `tvars'
- * @param variances The variances of type parameters; need to reverse
- * solution direction for all contravariant variables.
- * @param upper When `true' search for max solution else min.
- */
- def solve(tvars: List[TypeVar], tparams: List[Symbol],
- variances: List[Int], upper: Boolean): Boolean =
- solve(tvars, tparams, variances, upper, AnyDepth)
-
- def solve(tvars: List[TypeVar], tparams: List[Symbol],
- variances: List[Int], upper: Boolean, depth: Int): Boolean = {
- val config = tvars zip (tparams zip variances)
-
- def solveOne(tvar: TypeVar, tparam: Symbol, variance: Int) {
- if (tvar.constr.inst == NoType) {
- val up = if (variance != CONTRAVARIANT) upper else !upper
- tvar.constr.inst = null
- val bound: Type = if (up) tparam.info.bounds.hi else tparam.info.bounds.lo
- //Console.println("solveOne0(tv, tp, v, b)="+(tvar, tparam, variance, bound))
- var cyclic = bound contains tparam
- for ((tvar2, (tparam2, variance2)) <- config) {
- if (tparam2 != tparam &&
- ((bound contains tparam2) ||
- up && (tparam2.info.bounds.lo =:= tparam.tpe) ||
- !up && (tparam2.info.bounds.hi =:= tparam.tpe))) {
- if (tvar2.constr.inst eq null) cyclic = true
- solveOne(tvar2, tparam2, variance2)
- }
- }
- if (!cyclic) {
- if (up) {
- if (bound.typeSymbol != AnyClass)
- tvar addHiBound bound.instantiateTypeParams(tparams, tvars)
- for (tparam2 <- tparams)
- tparam2.info.bounds.lo.dealias match {
- case TypeRef(_, `tparam`, _) =>
- tvar addHiBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
- case _ =>
- }
- } else {
- if (bound.typeSymbol != NothingClass && bound.typeSymbol != tparam) {
- tvar addLoBound bound.instantiateTypeParams(tparams, tvars)
- }
- for (tparam2 <- tparams)
- tparam2.info.bounds.hi.dealias match {
- case TypeRef(_, `tparam`, _) =>
- tvar addLoBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
- case _ =>
- }
- }
- }
- tvar.constr.inst = NoType // necessary because hibounds/lobounds may contain tvar
-
- //println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen)))
-
- tvar setInst (
- if (up) {
- if (depth != AnyDepth) glb(tvar.constr.hiBounds, depth) else glb(tvar.constr.hiBounds)
- } else {
- if (depth != AnyDepth) lub(tvar.constr.loBounds, depth) else lub(tvar.constr.loBounds)
- })
-
- //Console.println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen))+" = "+tvar.constr.inst)//@MDEBUG
- }
- }
-
- // println("solving "+tvars+"/"+tparams+"/"+(tparams map (_.info)))
- for ((tvar, (tparam, variance)) <- config)
- solveOne(tvar, tparam, variance)
-
- tvars forall (tvar => tvar.constr.isWithinBounds(tvar.constr.inst))
- }
-
- /** Do type arguments `targs' conform to formal parameters
- * `tparams'?
- *
- * @param tparams ...
- * @param targs ...
- * @return ...
- */
- def isWithinBounds(pre: Type, owner: Symbol, tparams: List[Symbol], targs: List[Type]): Boolean = {
- var bounds = instantiatedBounds(pre, owner, tparams, targs)
- if (targs.exists(_.annotations.nonEmpty))
- bounds = adaptBoundsToAnnotations(bounds, tparams, targs)
- (bounds corresponds targs)(_ containsType _)
- }
-
- def instantiatedBounds(pre: Type, owner: Symbol, tparams: List[Symbol], targs: List[Type]): List[TypeBounds] =
- tparams map (_.info.asSeenFrom(pre, owner).instantiateTypeParams(tparams, targs).bounds)
-
-// Lubs and Glbs ---------------------------------------------------------
-
- /** The least sorted upwards closed upper bound of a non-empty list
- * of lists of types relative to the following ordering <= between lists of types:
- *
- * xs <= ys iff forall y in ys exists x in xs such that x <: y
- *
- * @See baseTypeSeq for a definition of sorted and upwards closed.
- */
- private def lubList(tss: List[List[Type]], depth: Int): List[Type] =
- if (tss.tail.isEmpty) tss.head
- else if (tss exists (_.isEmpty)) List()
- else {
- val ts0 = tss map (_.head)
- val sym = minSym(ts0)
- if (ts0 forall (_.typeSymbol == sym))
- mergePrefixAndArgs(elimSub(ts0, depth), 1, depth).toList ::: lubList(tss map (_.tail), depth)
- else
- lubList(tss map (ts => if (ts.head.typeSymbol == sym) ts.tail else ts), depth)
- }
-
- private def lubBaseTypeSeq(tss: List[BaseTypeSeq], depth: Int): List[Type] =
- lubList(tss map (_.toList), depth)
-
- /** The minimal symbol (wrt Symbol.isLess) of a list of types */
- private def minSym(tps: List[Type]): Symbol =
- (tps.head.typeSymbol /: tps.tail) {
- (sym1, tp2) => if (tp2.typeSymbol isLess sym1) tp2.typeSymbol else sym1
- }
-
- /** A minimal type list which has a given list of types as its base type sequence */
- def spanningTypes(ts: List[Type]): List[Type] = ts match {
- case List() => List()
- case first :: rest =>
- first :: spanningTypes(
- rest filter (t => !first.typeSymbol.isSubClass(t.typeSymbol)))
- }
-
- /** Eliminate from list of types all elements which are a supertype
- * of some other element of the list. */
- private def elimSuper(ts: List[Type]): List[Type] = ts match {
- case List() => List()
- case t :: ts1 =>
- val rest = elimSuper(ts1 filter (t1 => !(t <:< t1)))
- if (rest exists (t1 => t1 <:< t)) rest else t :: rest
- }
-
- /** A collector that tests for existential types appearing at given variance in a type */
- class ContainsVariantExistentialCollector(v: Int) extends TypeCollector(false) {
- def traverse(tp: Type) = tp match {
- case ExistentialType(_, _) if (variance == v) => result = true
- case _ => mapOver(tp)
- }
- def init() = {
- variance = 1
- this
- }
- }
-
- val containsCovariantExistentialCollector = new ContainsVariantExistentialCollector(1)
- val containsContravariantExistentialCollector = new ContainsVariantExistentialCollector(-1)
-
- /** Eliminate from list of types all elements which are a subtype
- * of some other element of the list. */
- private def elimSub(ts: List[Type], depth: Int): List[Type] = {
- def elimAnonymousClass(t: Type) = t match {
- case TypeRef(pre, clazz, List()) if clazz.isAnonymousClass =>
- clazz.classBound.asSeenFrom(pre, clazz.owner)
- case _ =>
- t
- }
- def elimSub0(ts: List[Type]): List[Type] = ts match {
- case List() => List()
- case t :: ts1 =>
- val rest = elimSub0(ts1 filter (t1 => !isSubType(t1, t, decr(depth))))
- if (rest exists (t1 => isSubType(t, t1, decr(depth)))) rest else t :: rest
- }
- val ts0 = elimSub0(ts)
- if (ts0.isEmpty || ts0.tail.isEmpty) ts0
- else {
- val ts1 = ts0 mapConserve (t => elimAnonymousClass(t.underlying))
- if (ts1 eq ts0) ts0
- else elimSub(ts1, depth)
- }
- }
-
- private def stripExistentialsAndTypeVars(ts: List[Type]): (List[Type], List[Symbol]) = {
- val quantified = ts flatMap {
- case ExistentialType(qs, _) => qs
- case t => List()
- }
- def stripType(tp: Type) = tp match {
- case ExistentialType(_, res) =>
- res
- case TypeVar(_, constr) =>
- if (constr.instValid) constr.inst
- else abort("trying to do lub/glb of typevar "+tp)
- case t => t
- }
- val strippedTypes = ts mapConserve stripType
- (strippedTypes, quantified)
- }
-
- def weakLub(ts: List[Type]) =
- if (ts.nonEmpty && (ts forall isNumericValueType)) (numericLub(ts), true)
- else if (ts.nonEmpty && (ts exists (_.annotations.nonEmpty)))
- (annotationsLub(lub(ts map (_.withoutAnnotations)), ts), true)
- else (lub(ts), false)
-
- def weakGlb(ts: List[Type]) = {
- if (ts.nonEmpty && (ts forall isNumericValueType)) {
- val nglb = numericGlb(ts)
- if (nglb != NoType) (nglb, true)
- else (glb(ts), false)
- } else if (ts.nonEmpty && (ts exists (_.annotations.nonEmpty))) {
- (annotationsGlb(glb(ts map (_.withoutAnnotations)), ts), true)
- } else (glb(ts), false)
- }
-
- def numericLub(ts: List[Type]) =
- ts reduceLeft ((t1, t2) =>
- if (isNumericSubType(t1, t2)) t2
- else if (isNumericSubType(t2, t1)) t1
- else IntClass.tpe)
-
- def numericGlb(ts: List[Type]) =
- ts reduceLeft ((t1, t2) =>
- if (isNumericSubType(t1, t2)) t1
- else if (isNumericSubType(t2, t1)) t2
- else NoType)
-
- def isWeakSubType(tp1: Type, tp2: Type) =
- tp1.deconst.normalize match {
- case TypeRef(_, sym1, _) if isNumericValueClass(sym1) =>
- tp2.deconst.normalize match {
- case TypeRef(_, sym2, _) if isNumericValueClass(sym2) =>
- isNumericSubClass(sym1, sym2)
- case tv2 @ TypeVar(_, _) =>
- tv2.registerBound(tp1, isLowerBound = true, isNumericBound = true)
- case _ =>
- isSubType(tp1, tp2)
- }
- case tv1 @ TypeVar(_, _) =>
- tp2.deconst.normalize match {
- case TypeRef(_, sym2, _) if isNumericValueClass(sym2) =>
- tv1.registerBound(tp2, isLowerBound = false, isNumericBound = true)
- case _ =>
- isSubType(tp1, tp2)
- }
- case _ =>
- isSubType(tp1, tp2)
- }
-
- def isNumericSubType(tp1: Type, tp2: Type) =
- isNumericValueType(tp1) && isNumericValueType(tp2) &&
- isNumericSubClass(tp1.typeSymbol, tp2.typeSymbol)
-
- private val lubResults = new mutable.HashMap[(Int, List[Type]), Type]
- private val glbResults = new mutable.HashMap[(Int, List[Type]), Type]
-
- def lub(ts: List[Type]): Type = try {
- lub(ts, lubDepth(ts))
- } finally {
- lubResults.clear()
- glbResults.clear()
- }
-
- /** The least upper bound wrt <:< of a list of types */
- def lub(ts: List[Type], depth: Int): Type = {
- def lub0(ts0: List[Type]): Type = elimSub(ts0, depth) match {
- case List() => NothingClass.tpe
- case List(t) => t
- case ts @ PolyType(tparams, _) :: _ =>
- val tparams1 = (tparams, matchingBounds(ts, tparams).transpose).zipped map
- ((tparam, bounds) => tparam.cloneSymbol.setInfo(glb(bounds, depth)))
- PolyType(tparams1, lub0(matchingInstTypes(ts, tparams1)))
- case ts @ MethodType(params, _) :: rest =>
- MethodType(params, lub0(matchingRestypes(ts, params map (_.tpe))))
- case ts @ NullaryMethodType(_) :: rest =>
- NullaryMethodType(lub0(matchingRestypes(ts, Nil)))
- case ts @ TypeBounds(_, _) :: rest =>
- TypeBounds(glb(ts map (_.bounds.lo), depth), lub(ts map (_.bounds.hi), depth))
- case ts =>
- lubResults get (depth, ts) match {
- case Some(lubType) =>
- lubType
- case None =>
- lubResults((depth, ts)) = AnyClass.tpe
- val res = if (depth < 0) AnyClass.tpe else lub1(ts)
- lubResults((depth, ts)) = res
- res
- }
- }
- def lub1(ts0: List[Type]): Type = {
- val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
- val bts: List[BaseTypeSeq] = ts map (_.baseTypeSeq)
- val lubBaseTypes: List[Type] = lubBaseTypeSeq(bts, depth)
- val lubParents = spanningTypes(lubBaseTypes)
- val lubOwner = commonOwner(ts)
- val lubBase = intersectionType(lubParents, lubOwner)
- val lubType =
- if (phase.erasedTypes || depth == 0) lubBase
- else {
- val lubRefined = refinedType(lubParents, lubOwner)
- val lubThisType = lubRefined.typeSymbol.thisType
- val narrowts = ts map (_.narrow)
- def lubsym(proto: Symbol): Symbol = {
- val prototp = lubThisType.memberInfo(proto)
- val syms = narrowts map (t =>
- t.nonPrivateMember(proto.name).suchThat(sym =>
- sym.tpe matches prototp.substThis(lubThisType.typeSymbol, t)))
- if (syms contains NoSymbol) NoSymbol
- else {
- val symtypes =
- (narrowts, syms).zipped map ((t, sym) => t.memberInfo(sym).substThis(t.typeSymbol, lubThisType))
- if (proto.isTerm) // possible problem: owner of info is still the old one, instead of new refinement class
- proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(lub(symtypes, decr(depth)))
- else if (symtypes.tail forall (symtypes.head =:=))
- proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(symtypes.head)
- else {
- def lubBounds(bnds: List[TypeBounds]): TypeBounds =
- TypeBounds(glb(bnds map (_.lo), decr(depth)), lub(bnds map (_.hi), decr(depth)))
- lubRefined.typeSymbol.newAbstractType(proto.pos, proto.name.toTypeName)
- .setInfoOwnerAdjusted(lubBounds(symtypes map (_.bounds)))
- }
- }
- }
- def refines(tp: Type, sym: Symbol): Boolean = {
- val syms = tp.nonPrivateMember(sym.name).alternatives;
- !syms.isEmpty && (syms forall (alt =>
- // todo alt != sym is strictly speaking not correct, but without it we lose
- // efficiency.
- alt != sym && !specializesSym(lubThisType, sym, tp, alt)))
- }
- for (sym <- lubBase.nonPrivateMembers) {
- // add a refinement symbol for all non-class members of lubBase
- // which are refined by every type in ts.
- if (!sym.isClass && !sym.isConstructor && (narrowts forall (t => refines(t, sym))))
- try {
- val lsym = lubsym(sym)
- if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lubsym(sym))
- } catch {
- case ex: NoCommonType =>
- }
- }
- if (lubRefined.decls.isEmpty) lubBase
- else {
-// println("refined lub of "+ts+"/"+narrowts+" is "+lubRefined+", baseclasses = "+(ts map (_.baseTypeSeq) map (_.toList)))
- lubRefined
- }
- }
- existentialAbstraction(tparams, lubType)
- }
- if (printLubs) {
- println(indent + "lub of " + ts + " at depth "+depth)//debug
- indent = indent + " "
- assert(indent.length <= 100)
- }
- val res = lub0(ts)
- if (printLubs) {
- indent = indent dropRight 2
- println(indent + "lub of " + ts + " is " + res)//debug
- }
- if (ts forall (_.isNotNull)) res.notNull else res
- }
-
- val GlbFailure = new Throwable
-
- /** A global counter for glb calls in the `specializes' query connected to the `addMembers'
- * call in `glb'. There's a possible infinite recursion when `specializes' calls
- * memberType, which calls baseTypeSeq, which calls mergePrefixAndArgs, which calls glb.
- * The counter breaks this recursion after two calls.
- * If the recursion is broken, no member is added to the glb.
- */
- private var globalGlbDepth = 0
- private final val globalGlbLimit = 2
-
- def glb(ts: List[Type]): Type = try {
- glb(ts, lubDepth(ts))
- } finally {
- lubResults.clear()
- glbResults.clear()
- }
-
- /** The greatest lower bound wrt <:< of a list of types */
- private def glb(ts: List[Type], depth: Int): Type = {
- def glb0(ts0: List[Type]): Type = elimSuper(ts0) match {
- case List() => AnyClass.tpe
- case List(t) => t
- case ts @ PolyType(tparams, _) :: _ =>
- val tparams1 = (tparams, matchingBounds(ts, tparams).transpose).zipped map
- ((tparam, bounds) => tparam.cloneSymbol.setInfo(lub(bounds, depth)))
- PolyType(tparams1, glb0(matchingInstTypes(ts, tparams1)))
- case ts @ MethodType(params, _) :: rest =>
- MethodType(params, glb0(matchingRestypes(ts, params map (_.tpe))))
- case ts @ NullaryMethodType(_) :: rest =>
- NullaryMethodType(glb0(matchingRestypes(ts, Nil)))
- case ts @ TypeBounds(_, _) :: rest =>
- TypeBounds(lub(ts map (_.bounds.lo), depth), glb(ts map (_.bounds.hi), depth))
- case ts =>
- glbResults get (depth, ts) match {
- case Some(glbType) =>
- glbType
- case _ =>
- glbResults((depth, ts)) = NothingClass.tpe
- val res = if (depth < 0) NothingClass.tpe else glb1(ts)
- glbResults((depth, ts)) = res
- res
- }
- }
- def glb1(ts0: List[Type]): Type = {
- try {
- val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
- val glbOwner = commonOwner(ts)
- def refinedToParents(t: Type): List[Type] = t match {
- case RefinedType(ps, _) => ps flatMap refinedToParents
- case _ => List(t)
- }
- def refinedToDecls(t: Type): List[Scope] = t match {
- case RefinedType(ps, decls) =>
- val dss = ps flatMap refinedToDecls
- if (decls.isEmpty) dss else decls :: dss
- case _ => List()
- }
- val ts1 = ts flatMap refinedToParents
- val glbBase = intersectionType(ts1, glbOwner)
- val glbType =
- if (phase.erasedTypes || depth == 0) glbBase
- else {
- val glbRefined = refinedType(ts1, glbOwner)
- val glbThisType = glbRefined.typeSymbol.thisType
- def glbsym(proto: Symbol): Symbol = {
- val prototp = glbThisType.memberInfo(proto)
- val syms = for (t <- ts;
- alt <- (t.nonPrivateMember(proto.name).alternatives);
- if glbThisType.memberInfo(alt) matches prototp
- ) yield alt
- val symtypes = syms map glbThisType.memberInfo
- assert(!symtypes.isEmpty)
- proto.cloneSymbol(glbRefined.typeSymbol).setInfoOwnerAdjusted(
- if (proto.isTerm) glb(symtypes, decr(depth))
- else {
- def isTypeBound(tp: Type) = tp match {
- case TypeBounds(_, _) => true
- case _ => false
- }
- def glbBounds(bnds: List[Type]): TypeBounds = {
- val lo = lub(bnds map (_.bounds.lo), decr(depth))
- val hi = glb(bnds map (_.bounds.hi), decr(depth))
- if (lo <:< hi) TypeBounds(lo, hi)
- else throw GlbFailure
- }
- val symbounds = symtypes filter isTypeBound
- var result: Type =
- if (symbounds.isEmpty)
- TypeBounds.empty
- else glbBounds(symbounds)
- for (t <- symtypes if !isTypeBound(t))
- if (result.bounds containsType t) result = t
- else throw GlbFailure
- result
- })
- }
- if (globalGlbDepth < globalGlbLimit)
- try {
- globalGlbDepth += 1
- val dss = ts flatMap refinedToDecls
- for (ds <- dss; val sym <- ds.iterator)
- if (globalGlbDepth < globalGlbLimit && !(glbThisType specializes sym))
- try {
- addMember(glbThisType, glbRefined, glbsym(sym))
- } catch {
- case ex: NoCommonType =>
- }
- } finally {
- globalGlbDepth -= 1
- }
- if (glbRefined.decls.isEmpty) glbBase else glbRefined
- }
- existentialAbstraction(tparams, glbType)
- } catch {
- case GlbFailure =>
- if (ts forall (t => NullClass.tpe <:< t)) NullClass.tpe
- else NothingClass.tpe
- }
- }
- // if (settings.debug.value) { println(indent + "glb of " + ts + " at depth "+depth); indent = indent + " " } //DEBUG
-
- val res = glb0(ts)
-
- // if (settings.debug.value) { indent = indent.substring(0, indent.length() - 2); log(indent + "glb of " + ts + " is " + res) }//DEBUG
-
- if (ts exists (_.isNotNull)) res.notNull else res
- }
-
- /** The most deeply nested owner that contains all the symbols
- * of thistype or prefixless typerefs/singletype occurrences in given type.
- */
- private def commonOwner(t: Type): Symbol = {
- commonOwnerMap.init
- commonOwnerMap.apply(t)
- commonOwnerMap.result
- }
-
- /** The most deeply nested owner that contains all the symbols
- * of thistype or prefixless typerefs/singletype occurrences in given list
- * of types.
- */
- private def commonOwner(tps: List[Type]): Symbol = {
- // if (settings.debug.value) log("computing common owner of types " + tps)//DEBUG
- commonOwnerMap.init
- tps foreach { tp => commonOwnerMap.apply(tp); () }
- commonOwnerMap.result
- }
-
- /** Compute lub (if variance == 1) or glb (if variance == -1) of given list
- * of types `tps'. All types in `tps' are typerefs or singletypes
- * with the same symbol.
- * Return `Some(x)' if the computation succeeds with result `x'.
- * Return `None' if the computation fails.
- */
- def mergePrefixAndArgs(tps: List[Type], variance: Int, depth: Int): Option[Type] = tps match {
- case List(tp) =>
- Some(tp)
- case TypeRef(_, sym, _) :: rest =>
- val pres = tps map (_.prefix) // prefix normalizes automatically
- val pre = if (variance == 1) lub(pres, depth) else glb(pres, depth)
- val argss = tps map (_.normalize.typeArgs) // symbol equality (of the tp in tps) was checked using typeSymbol, which normalizes, so should normalize before retrieving arguments
- val capturedParams = new ListBuffer[Symbol]
- try {
- if (sym == ArrayClass && phase.erasedTypes) {
- // special treatment for lubs of array types after erasure:
- // if argss contain one value type and some other type, the lub is Object
- // if argss contain several reference types, the lub is an array over lub of argtypes
- if (argss exists (_.isEmpty)) {
- None // something is wrong: an array without a type arg.
- } else {
- val args = argss map (_.head)
- if (args.tail forall (_ =:= args.head)) Some(typeRef(pre, sym, List(args.head)))
- else if (args exists (arg => isValueClass(arg.typeSymbol))) Some(ObjectClass.tpe)
- else Some(typeRef(pre, sym, List(lub(args))))
- }
- } else {
- val args = (sym.typeParams, argss.transpose).zipped map {
- (tparam, as) =>
- if (depth == 0)
- if (tparam.variance == variance) AnyClass.tpe
- else if (tparam.variance == -variance) NothingClass.tpe
- else NoType
- else
- if (tparam.variance == variance) lub(as, decr(depth))
- else if (tparam.variance == -variance) glb(as, decr(depth))
- else {
- val l = lub(as, decr(depth))
- val g = glb(as, decr(depth))
- if (l <:< g) l
- else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we
- // just err on the conservative side, i.e. with a bound that is too high.
- // if(!(tparam.info.bounds contains tparam)){ //@M can't deal with f-bounds, see #2251
-
- val qvar = commonOwner(as) freshExistential "" setInfo TypeBounds(g, l)
- capturedParams += qvar
- qvar.tpe
- }
- }
- }
- if (args contains NoType) None
- else Some(existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args)))
- }
- } catch {
- case ex: MalformedType => None
- case ex: IndexOutOfBoundsException => // transpose freaked out because of irregular argss
- // catching just in case (shouldn't happen, but also doesn't cost us)
- if (settings.debug.value) log("transposed irregular matrix!?"+ (tps, argss))
- None
- }
- case SingleType(_, sym) :: rest =>
- val pres = tps map (_.prefix)
- val pre = if (variance == 1) lub(pres, depth) else glb(pres, depth)
- try {
- Some(singleType(pre, sym))
- } catch {
- case ex: MalformedType => None
- }
- case ExistentialType(tparams, quantified) :: rest =>
- mergePrefixAndArgs(quantified :: rest, variance, depth) map (existentialAbstraction(tparams, _))
- case _ =>
- assert(false, tps); None
- }
-
- /** Make symbol `sym' a member of scope `tp.decls'
- * where `thistp' is the narrowed owner type of the scope.
- */
- def addMember(thistp: Type, tp: Type, sym: Symbol) {
- assert(sym != NoSymbol)
- // if (settings.debug.value) log("add member " + sym+":"+sym.info+" to "+thistp) //DEBUG
- if (!(thistp specializes sym)) {
- if (sym.isTerm)
- for (alt <- tp.nonPrivateDecl(sym.name).alternatives)
- if (specializesSym(thistp, sym, thistp, alt))
- tp.decls unlink alt;
- tp.decls enter sym
- }
- }
-
- /** All types in list must be polytypes with type parameter lists of
- * same length as tparams.
- * Returns list of list of bounds infos, where corresponding type
- * parameters are renamed to tparams.
- */
- private def matchingBounds(tps: List[Type], tparams: List[Symbol]): List[List[Type]] =
- tps map {
- case PolyType(tparams1, _) if sameLength(tparams1, tparams) =>
- tparams1 map (tparam => tparam.info.substSym(tparams1, tparams))
- case _ =>
- throw new NoCommonType(tps)
- }
-
- /** All types in list must be polytypes with type parameter lists of
- * same length as tparams.
- * Returns list of instance types, where corresponding type
- * parameters are renamed to tparams.
- */
- private def matchingInstTypes(tps: List[Type], tparams: List[Symbol]): List[Type] =
- tps map {
- case PolyType(tparams1, restpe) if sameLength(tparams1, tparams) =>
- restpe.substSym(tparams1, tparams)
- case _ =>
- throw new NoCommonType(tps)
- }
-
- /** All types in list must be method types with equal parameter types.
- * Returns list of their result types.
- */
- private def matchingRestypes(tps: List[Type], pts: List[Type]): List[Type] =
- tps map {
- case MethodType(params1, res) if (isSameTypes(params1 map (_.tpe), pts)) =>
- res
- case NullaryMethodType(res) if pts isEmpty =>
- res
- case _ =>
- throw new NoCommonType(tps)
- }
-
-
-// TODO: this desperately needs to be cleaned up
-// plan: split into kind inference and subkinding
-// every Type has a (cached) Kind
- def kindsConform(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): Boolean = checkKindBounds0(tparams, targs, pre, owner, false).isEmpty
-
- /** Check well-kindedness of type application (assumes arities are already checked) -- @M
- *
- * This check is also performed when abstract type members become concrete (aka a "type alias") -- then tparams.length==1
- * (checked one type member at a time -- in that case, prefix is the name of the type alias)
- *
- * Type application is just like value application: it's "contravariant" in the sense that
- * the type parameters of the supplied type arguments must conform to the type parameters of
- * the required type parameters:
- * - their bounds must be less strict
- * - variances must match (here, variances are absolute, the variance of a type parameter does not influence the variance of its higher-order parameters)
- * - @M TODO: are these conditions correct,sufficient&necessary?
- *
- * e.g. class Iterable[t, m[+x <: t]] --> the application Iterable[Int, List] is okay, since
- * List's type parameter is also covariant and its bounds are weaker than <: Int
- */
- def checkKindBounds0(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol, explainErrors: Boolean): List[(Type, Symbol, List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)])] = {
- var error = false
-
- def transform(tp: Type, clazz: Symbol): Type = tp.asSeenFrom(pre, clazz) // instantiate type params that come from outside the abstract type we're currently checking
- def transformedBounds(p: Symbol, o: Symbol) = transform(p.info.instantiateTypeParams(tparams, targs).bounds, o)
-
- /** Check whether <arg>sym1</arg>'s variance conforms to <arg>sym2</arg>'s variance
- *
- * If <arg>sym2</arg> is invariant, <arg>sym1</arg>'s variance is irrelevant. Otherwise they must be equal.
- */
- def variancesMatch(sym1: Symbol, sym2: Symbol): Boolean = (sym2.variance==0 || sym1.variance==sym2.variance)
-
- // check that the type parameters <arg>hkargs</arg> to a higher-kinded type conform to the expected params <arg>hkparams</arg>
- def checkKindBoundsHK(hkargs: List[Symbol], arg: Symbol, param: Symbol, paramowner: Symbol, underHKParams: List[Symbol], withHKArgs: List[Symbol]): (List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)]) = {
- def bindHKParams(tp: Type) = tp.substSym(underHKParams, withHKArgs)
- // @M sometimes hkargs != arg.typeParams, the symbol and the type may have very different type parameters
- val hkparams = param.typeParams
-
- if (settings.debug.value) {
- log("checkKindBoundsHK expected: "+ param +" with params "+ hkparams +" by definition in "+ paramowner)
- log("checkKindBoundsHK supplied: "+ arg +" with params "+ hkargs +" from "+ owner)
- log("checkKindBoundsHK under params: "+ underHKParams +" with args "+ withHKArgs)
- }
-
- if (!sameLength(hkargs, hkparams)) {
- if(arg == AnyClass || arg == NothingClass) (Nil, Nil, Nil) // Any and Nothing are kind-overloaded
- else {error = true; (List((arg, param)), Nil, Nil)} // shortcut: always set error, whether explainTypesOrNot
- } else {
- val _arityMismatches = if(explainErrors) new ListBuffer[(Symbol, Symbol)] else null
- val _varianceMismatches = if(explainErrors) new ListBuffer[(Symbol, Symbol)] else null
- val _stricterBounds = if(explainErrors)new ListBuffer[(Symbol, Symbol)] else null
- def varianceMismatch(a: Symbol, p: Symbol) { if(explainErrors) _varianceMismatches += ((a, p)) else error = true}
- def stricterBound(a: Symbol, p: Symbol) { if(explainErrors) _stricterBounds += ((a, p)) else error = true }
- def arityMismatches(as: Iterable[(Symbol, Symbol)]) { if(explainErrors) _arityMismatches ++= as }
- def varianceMismatches(as: Iterable[(Symbol, Symbol)]) { if(explainErrors) _varianceMismatches ++= as }
- def stricterBounds(as: Iterable[(Symbol, Symbol)]) { if(explainErrors) _stricterBounds ++= as }
-
- for ((hkarg, hkparam) <- hkargs zip hkparams) {
- if (hkparam.typeParams.isEmpty && hkarg.typeParams.isEmpty) { // base-case: kind *
- if (!variancesMatch(hkarg, hkparam))
- varianceMismatch(hkarg, hkparam)
-
- // instantiateTypeParams(tparams, targs) --> higher-order bounds may contain references to type arguments
- // substSym(hkparams, hkargs) --> these types are going to be compared as types of kind *
- // --> their arguments use different symbols, but are conceptually the same
- // (could also replace the types by polytypes, but can't just strip the symbols, as ordering is lost then)
- if (!(bindHKParams(transformedBounds(hkparam, paramowner)) <:< transform(hkarg.info.bounds, owner)))
- stricterBound(hkarg, hkparam)
-
- if (settings.debug.value) {
- log("checkKindBoundsHK base case: "+ hkparam +" declared bounds: "+ transformedBounds(hkparam, paramowner) +" after instantiating earlier hkparams: "+ bindHKParams(transformedBounds(hkparam, paramowner)))
- log("checkKindBoundsHK base case: "+ hkarg +" has bounds: "+ transform(hkarg.info.bounds, owner))
- }
- } else {
- if(settings.debug.value) log("checkKindBoundsHK recursing to compare params of "+ hkparam +" with "+ hkarg)
- val (am, vm, sb) = checkKindBoundsHK(hkarg.typeParams, hkarg, hkparam, paramowner, underHKParams ++ hkparam.typeParams, withHKArgs ++ hkarg.typeParams)
- arityMismatches(am)
- varianceMismatches(vm)
- stricterBounds(sb)
- }
- if(!explainErrors && error) return (Nil, Nil, Nil) // stop as soon as we encountered an error
- }
- if(!explainErrors) (Nil, Nil, Nil)
- else (_arityMismatches.toList, _varianceMismatches.toList, _stricterBounds.toList)
- }
- }
-
- val errors = new ListBuffer[(Type, Symbol, List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)])]
- (tparams zip targs).foreach{ case (tparam, targ) if (targ.isHigherKinded || !tparam.typeParams.isEmpty) =>
- // @M must use the typeParams of the type targ, not the typeParams of the symbol of targ!!
- targ.typeSymbolDirect.info // force symbol load for #4205
- val tparamsHO = targ.typeParams
-
- val (arityMismatches, varianceMismatches, stricterBounds) =
- checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO) // NOTE: *not* targ.typeSymbol, which normalizes
-
- if(!explainErrors) {if(error) return List((NoType, NoSymbol, Nil, Nil, Nil))}
- else if (arityMismatches.nonEmpty || varianceMismatches.nonEmpty || stricterBounds.nonEmpty) {
- errors += ((targ, tparam, arityMismatches, varianceMismatches, stricterBounds))
- }
- // case (tparam, targ) => println("no check: "+(tparam, targ, tparam.typeParams.isEmpty))
- case _ =>
- }
-
- errors.toList
- }
-
-// Errors and Diagnostics -----------------------------------------------------
-
- /** A throwable signalling a type error */
- class TypeError(var pos: Position, val msg: String) extends Throwable(msg) {
- def this(msg: String) = this(NoPosition, msg)
- }
-
- class NoCommonType(tps: List[Type]) extends Throwable(
- "lub/glb of incompatible types: " + tps.mkString("", " and ", "")) with ControlThrowable
-
- /** A throwable signalling a malformed type */
- class MalformedType(msg: String) extends TypeError(msg) {
- def this(pre: Type, tp: String) = this("malformed type: " + pre + "#" + tp)
- }
-
- /** An exception signalling a variance annotation/usage conflict */
- class VarianceError(msg: String) extends TypeError(msg)
-
- /** The current indentation string for traces */
- private var indent: String = ""
-
- /** Perform operation `p' on arguments `tp1',
- * `arg2' and print trace of computation.
- */
- private def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = {
- Console.println(indent + tp1 + " " + op + " " + arg2 + "?" /* + "("+tp1.getClass+","+arg2.asInstanceOf[AnyRef].getClass+")"*/)
- indent = indent + " "
- val result = p(tp1, arg2)
- indent = indent dropRight 2
- Console.println(indent + result)
- result
- }
-
- /** If option `explaintypes' is set, print a subtype trace for
- * `found <:< required'.
- */
- def explainTypes(found: Type, required: Type) {
- if (settings.explaintypes.value) withTypesExplained(found <:< required)
- }
-
- /** If option `explaintypes' is set, print a subtype trace for
- * `op(found, required)'.
- */
- def explainTypes(op: (Type, Type) => Any, found: Type, required: Type) {
- if (settings.explaintypes.value) withTypesExplained(op(found, required))
- }
-
- /** Execute `op' while printing a trace of the operations on types executed.
- */
- def withTypesExplained[A](op: => A): A = {
- val s = explainSwitch
- try { explainSwitch = true; op } finally { explainSwitch = s }
- }
-
- def objToAny(tp: Type): Type =
- if (!phase.erasedTypes && tp.typeSymbol == ObjectClass) AnyClass.tpe
- else tp
-
- val shorthands = Set(
- "scala.collection.immutable.List",
- "scala.collection.immutable.Nil",
- "scala.collection.Seq",
- "scala.collection.Traversable",
- "scala.collection.Iterable",
- "scala.collection.mutable.StringBuilder",
- "scala.collection.IndexedSeq",
- "scala.collection.Iterator")
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 08094d4104..cc63a43ca4 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -12,9 +12,8 @@ import java.lang.Integer.toHexString
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.{ ListBuffer, ArrayBuffer }
-import scala.tools.nsc.io.AbstractFile
import scala.annotation.switch
-import reflect.generic.PickleBuffer
+import scala.reflect.common.pickling.{PickleBuffer, ByteCodecs}
/** This abstract class implements a class file parser.
*
@@ -49,7 +48,7 @@ abstract class ClassfileParser {
val global: ClassfileParser.this.global.type = ClassfileParser.this.global
}
- private object unpickler extends UnPickler {
+ private object unpickler extends scala.reflect.common.pickling.UnPickler {
val global: ClassfileParser.this.global.type = ClassfileParser.this.global
}
@@ -376,7 +375,7 @@ abstract class ClassfileParser {
val len = in.getChar(start + 1)
val bytes = new Array[Byte](len)
Array.copy(in.buf, start + 3, bytes, 0, len)
- val decodedLength = reflect.generic.ByteCodecs.decode(bytes)
+ val decodedLength = ByteCodecs.decode(bytes)
value = bytes.take(decodedLength)
values(index) = value
}
@@ -396,7 +395,7 @@ abstract class ClassfileParser {
bytesBuffer ++= in.buf.view(start + 3, start + 3 + len)
}
val bytes = bytesBuffer.toArray
- val decodedLength = reflect.generic.ByteCodecs.decode(bytes)
+ val decodedLength = ByteCodecs.decode(bytes)
value = bytes.take(decodedLength)
values(indices.head) = value
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index ac2cd9e996..0eb290c988 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -10,7 +10,6 @@ package classfile
import scala.collection.{ mutable, immutable }
import mutable.ListBuffer
import backend.icode._
-import io.AbstractFile
import ClassfileConstants._
import Flags._
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 131c935a8a..ea1283cfaa 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -10,7 +10,7 @@ package classfile
import java.lang.Float.floatToIntBits
import java.lang.Double.doubleToLongBits
import scala.io.Codec
-import reflect.generic.{ PickleBuffer, PickleFormat }
+import scala.reflect.common.pickling.{ PickleBuffer, PickleFormat }
import scala.collection.mutable.LinkedHashMap
import PickleFormat._
import Flags._
@@ -30,6 +30,8 @@ abstract class Pickler extends SubComponent {
val phaseName = "pickler"
+ currentRun
+
def newPhase(prev: Phase): StdPhase = new PicklePhase(prev)
class PicklePhase(prev: Phase) extends StdPhase(prev) {
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 536e8e89c1..e69de29bb2 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -1,77 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-package classfile
-
-import Flags._
-import scala.reflect.generic.PickleFormat._
-
-/** @author Martin Odersky
- * @version 1.0
- */
-abstract class UnPickler extends reflect.generic.UnPickler {
- val global: Global
- import global._
-
- def scan(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) =
- new CompileScan(bytes, offset, classRoot, moduleRoot, filename).run()
-
- class CompileScan(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String)
- extends Scan(bytes, offset, classRoot, moduleRoot, filename) {
-
- protected override def debug = settings.debug.value
-
- // override def noSuchTypeTag(tag: Int, end: Int): Type = {
- // tag match {
- // case DEBRUIJNINDEXtpe =>
- // DeBruijnIndex(readNat(), readNat())
- // case _ =>
- // super.noSuchTypeTag(tag, end)
- // }
- // }
-
- override protected def errorMissingRequirement(name: Name, owner: Symbol) =
- errorMissingRequirement(
- "reference " + (if (name.isTypeName) "type " else "value ") +
- name.decode + " of " + owner.tpe.widen + " refers to nonexisting symbol.")
-
- def inferMethodAlternative(fun: Tree, argtpes: List[Type], restpe: Type) =
- typer.infer.inferMethodAlternative(fun, List(), argtpes, restpe)
-
- def newLazyTypeRef(i: Int): LazyType = new LazyTypeRef(i)
- def newLazyTypeRefAndAlias(i: Int, j: Int): LazyType = new LazyTypeRefAndAlias(i, j)
-
- /** A lazy type which when completed returns type at index `i`. */
- private class LazyTypeRef(i: Int) extends LazyType {
- private val definedAtRunId = currentRunId
- private val p = phase
- override def complete(sym: Symbol) : Unit = {
- val tp = at(i, () => readType(sym.isTerm)) // after NMT_TRANSITION, revert `() => readType(sym.isTerm)` to `readType`
- if (p != phase) atPhase(p) (sym setInfo tp)
- else sym setInfo tp
- if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp))
- }
- override def load(sym: Symbol) { complete(sym) }
- }
-
- /** A lazy type which when completed returns type at index `i` and sets alias
- * of completed symbol to symbol at index `j`.
- */
- private class LazyTypeRefAndAlias(i: Int, j: Int) extends LazyTypeRef(i) {
- override def complete(sym: Symbol) {
- super.complete(sym)
- var alias = at(j, readSymbol)
- if (alias.isOverloaded) {
- atPhase(currentRun.picklerPhase) {
- alias = alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt))
- }
- }
- sym.asInstanceOf[TermSymbol].setAlias(alias)
- }
- }
- }
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
index 37b81a8fc1..6242a22bfa 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
@@ -12,7 +12,7 @@ import java.io.IOException
import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute, _}
import scala.collection.mutable.{HashMap, HashSet}
-import classfile.UnPickler
+import scala.reflect.common.pickling.UnPickler
import ch.epfl.lamp.compiler.msil.Type.TMVarUsage
/**
diff --git a/src/compiler/scala/tools/nsc/transform/Reifiers.scala b/src/compiler/scala/tools/nsc/transform/Reifiers.scala
index 6b0d441ad9..d938a20f2f 100644
--- a/src/compiler/scala/tools/nsc/transform/Reifiers.scala
+++ b/src/compiler/scala/tools/nsc/transform/Reifiers.scala
@@ -12,7 +12,7 @@ import collection.mutable.HashMap
* @author Gilles Dubochet, Lex Spoon
*/
trait Reifiers {
- val symbols: SymbolTable
+ val symbols: Global
import symbols._
private def mkGlobalSymbol(fullname: String, sym: Symbol): reflect.Symbol =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index ee35cfa267..7550fc3739 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -288,6 +288,12 @@ trait Contexts { self: Analyzer =>
else throw new TypeError(pos, msg1)
}
+/*!!! def errorTree(pos: Position, msg: String): ErrorTree = {
+ error(pos, msg)
+ ErrorTree(msg) setPos pos
+ }
+ */
+
def warning(pos: Position, msg: String) = {
if (reportGeneralErrors) unit.warning(pos, msg)
}