summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-06-09 13:03:55 +0000
committerMartin Odersky <odersky@gmail.com>2007-06-09 13:03:55 +0000
commit8414ebada9615aac0e8b436e7bdbeee5986ccaa3 (patch)
treef62c23aec3d9f49446aebd76963667be8468f48d /src
parent6ad83dae6960a78d6014c6fcfee1889a322ad5d7 (diff)
downloadscala-8414ebada9615aac0e8b436e7bdbeee5986ccaa3.tar.gz
scala-8414ebada9615aac0e8b436e7bdbeee5986ccaa3.tar.bz2
scala-8414ebada9615aac0e8b436e7bdbeee5986ccaa3.zip
added existential types
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala10
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala56
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala30
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala256
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala159
12 files changed, 416 insertions, 163 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index 25649d8941..479911b92b 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -720,7 +720,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
case rawType => rawType
}
- map + name -> cleanedType.toString
+ map + name -> compiler.atPhase(objRun.typerPhase.next) { cleanedType.toString }
})
}
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index 4d1cd80d84..7a847b148b 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -185,6 +185,7 @@ abstract class NodePrinters {
traverse(tparams(i), level + 2, i < n-1)
println(" ),")
}
+ println(tpt+",")
traverse(rhs, level + 1, false)
printcln(")")
case EmptyTree =>
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 3d8e546729..f19a0d1092 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -252,6 +252,12 @@ abstract class TreePrinters {
case Throw(expr) =>
print("throw "); print(expr)
+ case Pack(expr) =>
+ print("pack("); print(expr); print(")")
+
+ case Unpack(expr) =>
+ print("unpack("); print(expr); print(")")
+
case New(tpe) =>
print("new "); print(tpe)
@@ -327,6 +333,10 @@ abstract class TreePrinters {
case WildcardTypeTree(lo, hi) =>
print("_ "); printOpt(" >: ", lo); printOpt(" <: ", hi)
+ case ExistentialTypeTree(tpt, whereClauses) =>
+ print(tpt);
+ printColumn(whereClauses, " for_some { ", ";", "}")
+
case tree =>
print("<unknown tree of class "+tree.getClass+">")
}
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index f48c389646..5b22fcaaf8 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -11,6 +11,7 @@ import java.io.{PrintWriter, StringWriter}
import scala.tools.nsc.symtab.Flags
import scala.tools.nsc.symtab.Flags._
import scala.tools.nsc.util.{HashSet, Position, NoPosition, SourceFile}
+import scala.collection.mutable.ListBuffer
trait Trees {
@@ -98,6 +99,16 @@ trait Trees {
def isErroneous = (tpe ne null) && tpe.isErroneous
+ /** Apply `f' to each subtree */
+ def foreach(f: Tree => Unit): Unit = new ForeachTraverser(f).traverse(this)
+
+ /** Find all subtrees matching predicate `p' */
+ def filter(f: Tree => Boolean): List[Tree] = {
+ val ft = new FilterTraverser(f)
+ ft.traverse(this)
+ ft.hits.toList
+ }
+
override def toString(): String = {
val buffer = new StringWriter()
val printer = treePrinters.create(new PrintWriter(buffer))
@@ -585,6 +596,14 @@ trait Trees {
case class Throw(expr: Tree)
extends TermTree
+ /** Pack skolemized type, yielding existential */
+ case class Pack(expr: Tree)
+ extends TermTree
+
+ /** Unpack existential, yielding skolemized type */
+ case class Unpack(expr: Tree)
+ extends TermTree
+
/** Object instantiation
* One should always use factory method below to build a user level new.
*
@@ -787,6 +806,10 @@ trait Trees {
// try block catch { catches } finally finalizer where catches: List[CaseDef]
case Throw(expr) =>
// throw expr
+ case Pack(expr) => (eliminated by erasure)
+ // internal: pack existential type
+ case Unpack(expr) => (eliminated by erasure)
+ // internal: unpack existential type
case New(tpt) =>
// new tpt always in the context: new tpt.<init>[targs](args)
case Typed(expr, tpt) => (eliminated by erasure)
@@ -853,6 +876,8 @@ trait Trees {
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 Pack(tree: Tree, expr: Tree): Pack
+ def Unpack(tree: Tree, expr: Tree): Unpack
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
@@ -928,6 +953,10 @@ trait Trees {
new Try(block, catches, finalizer).copyAttrs(tree)
def Throw(tree: Tree, expr: Tree) =
new Throw(expr).copyAttrs(tree)
+ def Pack(tree: Tree, expr: Tree) =
+ new Pack(expr).copyAttrs(tree)
+ def Unpack(tree: Tree, expr: Tree) =
+ new Unpack(expr).copyAttrs(tree)
def New(tree: Tree, tpt: Tree) =
new New(tpt).copyAttrs(tree)
def Typed(tree: Tree, expr: Tree, tpt: Tree) =
@@ -1104,6 +1133,16 @@ trait Trees {
if expr0 == expr => t
case _ => copy.Throw(tree, expr)
}
+ def Pack(tree: Tree, expr: Tree) = tree match {
+ case t @ Pack(expr0)
+ if expr0 == expr => t
+ case _ => copy.Pack(tree, expr)
+ }
+ def Unpack(tree: Tree, expr: Tree) = tree match {
+ case t @ Unpack(expr0)
+ if expr0 == expr => t
+ case _ => copy.Unpack(tree, expr)
+ }
def New(tree: Tree, tpt: Tree) = tree match {
case t @ New(tpt0)
if tpt0 == tpt => t
@@ -1275,6 +1314,10 @@ trait Trees {
copy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer))
case Throw(expr) =>
copy.Throw(tree, transform(expr))
+ case Pack(expr) =>
+ copy.Pack(tree, transform(expr))
+ case Unpack(expr) =>
+ copy.Unpack(tree, transform(expr))
case New(tpt) =>
copy.New(tree, transform(tpt))
case Typed(expr, tpt) =>
@@ -1423,6 +1466,10 @@ trait Trees {
traverse(block); traverseTrees(catches); traverse(finalizer)
case Throw(expr) =>
traverse(expr)
+ case Pack(expr) =>
+ traverse(expr)
+ case Unpack(expr) =>
+ traverse(expr)
case New(tpt) =>
traverse(tpt)
case Typed(expr, tpt) =>
@@ -1544,6 +1591,15 @@ trait Trees {
}
}
+ class ForeachTraverser(f: Tree => Unit) extends Traverser {
+ override def traverse(t: Tree) = f(t)
+ }
+
+ class FilterTraverser(p: Tree => Boolean) extends Traverser {
+ val hits = new ListBuffer[Tree]
+ override def traverse(t: Tree) = if (p(t)) hits += t
+ }
+
object resetPos extends Traverser {
override def traverse(t: Tree): unit = {
if (t != EmptyTree) t.setPos(NoPosition)
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index 83b538ee9d..f9296da61b 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -66,6 +66,7 @@ object Flags extends Enumeration {
// local value has been lifted out to class level
// todo: make LIFTED = latePRIVATE?
final val MIXEDIN = 0x800000000L // term member has been mixed in
+ final val EXISTENTIAL = 0x800000000L // type is an existential parameter or skolem
final val EXPANDEDNAME = 0x1000000000L // name has been expanded with class suffix
final val IMPLCLASS = 0x2000000000L // symbol is an implementation class
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 450b162d01..c21a606ec4 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -115,9 +115,6 @@ trait Symbols {
}
final def newThisSym(pos: Position) =
newValue(pos, nme.this_).setFlag(SYNTHETIC)
- final def newThisSkolem: Symbol =
- new ThisSkolem(owner, pos, name, this)
- .setFlag(SYNTHETIC | FINAL)
final def newImport(pos: Position) =
newValue(pos, nme.IMPORT)
final def newOverloaded(pre: Type, alternatives: List[Symbol]): Symbol =
@@ -196,14 +193,18 @@ trait Symbols {
final def isStaticModule = isModule && isStatic && !isMethod
final def isPackage = isModule && hasFlag(PACKAGE)
final def isThisSym = isTerm && owner.thisSym == this
- final def isThisSkolem = isTerm && deSkolemize != this
final def isMonomorphicType = isType && hasFlag(MONOMORPHIC)
final def isError = hasFlag(IS_ERROR)
final def isErroneous = isError || isInitialized && tpe.isErroneous
final def isTrait = isClass & hasFlag(TRAIT)
+ final def isSkolem = deSkolemize != this
final def isTypeParameterOrSkolem = isType && hasFlag(PARAM)
- final def isTypeParameter = isTypeParameterOrSkolem && deSkolemize == this
- final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
+ final def isTypeParameter = isTypeParameterOrSkolem && !isSkolem
+ final def isTypeSkolem = isTypeParameterOrSkolem && isSkolem
+ final def isExistential = isType && hasFlag(EXISTENTIAL)
+ final def isExistentialQuantified = isExistential && !isSkolem
+ final def isExistentialSkolem = isExistential && isSkolem
+ final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME)
// startsWith necessary because name may grow when lifted and also because of anonymous function classes
final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME.toTypeName; // no lifting for refinement classes
@@ -1129,17 +1130,6 @@ trait Symbols {
}
}
- /** A class for type parameters viewed from inside their scopes */
- class ThisSkolem(initOwner: Symbol, initPos: Position,
- initName: Name, clazz: Symbol)
- extends TermSymbol(initOwner, initPos, initName) {
- override def deSkolemize = clazz
- override def cloneSymbolImpl(owner: Symbol): Symbol = {
- throw new Error("should not clone a this skolem")
- }
- override def nameString: String = clazz.name.toString() + ".this"
- }
-
/** A class of type symbols. Alias and abstract types are direct instances
* of this class. Classes are instances of a subclass.
*/
@@ -1168,7 +1158,8 @@ trait Symbols {
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 = typeRef(if (isTypeParameterOrSkolem) NoPrefix else owner.thisType, this, targs)
+ tpeCache = typeRef(if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType,
+ this, targs)
}
}
assert(tpeCache ne null/*, "" + this + " " + phase*/)//debug
@@ -1177,7 +1168,8 @@ trait Symbols {
override def typeConstructor: Type = {
if ((tyconCache eq null) || tyconRunId != currentRunId) {
- tyconCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, this, List())
+ tyconCache = typeRef(if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType,
+ this, List())
tyconRunId = currentRunId
}
assert(tyconCache ne null)
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index f948afeed0..f1c041ac35 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -121,6 +121,7 @@ trait Types {
override def notNull = maybeRewrap(tp.notNull)
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) =
tp.instantiateTypeParams(formals, actuals)
+ override def skolemizeExistential(owner: Symbol) = tp.skolemizeExistential(owner)
override def normalize = maybeRewrap(tp.normalize)
override def decls = tp.decls
override def baseType(clazz: Symbol) = tp.baseType(clazz)
@@ -178,7 +179,7 @@ trait Types {
* identity for all other types */
def deconst: Type = this
- /** The type of <code>this</code> of a class type or reference type
+ /** The type of `this' of a class type or reference type
*/
def typeOfThis: Type = symbol.typeOfThis
@@ -240,6 +241,8 @@ trait Types {
*/
def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type = this.subst(formals, actuals)
+ def skolemizeExistential(owner: Symbol) = this
+
/** Reduce to beta eta-long normal form. Expands type aliases and converts higher-kinded TypeRef's to PolyTypes. @M */
def normalize = this // @MAT
@@ -261,7 +264,7 @@ trait Types {
* The empty scope for all other types */
def decls: Scope = EmptyScope
- /** The defined or declared members with name <code>name</code> in this type;
+ /** 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.
*/
@@ -305,11 +308,11 @@ trait Types {
* of this type */
def baseType(clazz: Symbol): Type = NoType
- /** This type as seen from prefix <code>pre</code> and class
- * <code>clazz</code>. This means:
- * Replace all thistypes of <code>clazz</code> or one of its subclasses
- * by <code>pre</code> and instantiate all parameters by arguments of
- * <code>pre</code>.
+ /** 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.
*/
def asSeenFrom(pre: Type, clazz: Symbol): Type =
@@ -317,7 +320,7 @@ trait Types {
new AsSeenFromMap(pre, clazz) apply this
} else this
- /** The info of <code>sym</code>, seen as a member of this type.
+ /** The info of `sym', seen as a member of this type.
*/
def memberInfo(sym: Symbol): Type =
sym.info.asSeenFrom(this, sym.owner)
@@ -347,20 +350,20 @@ trait Types {
}
}
- /** Substitute types <code>to</code> for occurrences of references to
- * symbols <code>from</code> in this type.
+ /** 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 <code>to</code> for occurrences of symbols
- * <code>from</code> in this type.
+ /** Substitute symbols `to' for occurrences of symbols
+ * `from' in this type.
*/
def substSym(from: List[Symbol], to: List[Symbol]): Type =
new SubstSymMap(from, to) apply this
- /** Substitute all occurrences of <code>ThisType(from)</code> in this type
- * by <code>to</code>.
+ /** Substitute all occurrences of `ThisType(from)' in this type
+ * by `to'.
*/
def substThis(from: Symbol, to: Type): Type =
new SubstThisMap(from, to) apply this
@@ -368,6 +371,24 @@ trait Types {
def substSuper(from: Type, to: Type): Type =
new SubstSuperMap(from, to) apply this
+ def exskolems: List[Symbol] =
+ this filter (_.symbol.isExistentialSkolem) map (_.symbol)
+
+ /** Returns all parts of this type which satisfy predicate `p' */
+ def filter(p: Type => Boolean): List[Type] = {
+ new FilterTraverser(p).traverse(this).hits.toList
+ }
+
+ /** Returns optionally first type (in a preorder traverser) which satisfies predicate `p',
+ * or None if none exists.
+ */
+ def find(p: Type => boolean): Option[Type] = {
+ new FindTraverser(p).traverse(this).result
+ }
+
+ /** 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 ContainsTraverser(sym).traverse(this).result
@@ -396,7 +417,7 @@ trait Types {
else isSameType(this, that))
);
- /** Does this type implement symbol <code>sym</code> with same or stronger type?
+ /** Does this type implement symbol `sym' with same or stronger type?
*/
def specializes(sym: Symbol): boolean =
if (explainSwitch) explain("specializes", specializesSym, this, sym)
@@ -464,7 +485,7 @@ trait Types {
}
/** If this is a polytype, a copy with cloned type parameters owned
- * by <code>owner</code>. Identity for all other types.
+ * by `owner'. Identity for all other types.
*/
def cloneInfo(owner: Symbol) = this
@@ -490,11 +511,11 @@ trait Types {
*/
def isComplete: boolean = true
- /** If this is a lazy type, assign a new type to <code>sym</code>. */
+ /** If this is a lazy type, assign a new type to `sym'. */
def complete(sym: Symbol) = {}
/** If this is a symbol loader type, load and assign a new type to
- * <code>sym</code>.
+ * `sym'.
*/
def load(sym: Symbol): unit = {}
@@ -737,7 +758,7 @@ trait Types {
/** A class for singleton types of the form &lt;prefix&gt;.&lt;sym.name&gt;.type.
* Cannot be created directly; one should always use
- * <code>singleType</code> for creation.
+ * `singleType' for creation.
*/
case class SingleType(pre: Type, sym: Symbol) extends SingletonType {
override val isTrivial: boolean = pre.isTrivial
@@ -973,9 +994,9 @@ trait Types {
}
/** A class representing intersection types with refinements of the form
- * <code>&lt;parents_0&gt; with ... with &lt;parents_n&gt; { decls }</code>
+ * `&lt;parents_0&gt; with ... with &lt;parents_n&gt; { decls }'
* Cannot be created directly;
- * one should always use <code>refinedType</code> for creation.
+ * one should always use `refinedType' for creation.
*/
case class RefinedType(override val parents: List[Type],
override val decls: Scope) extends CompoundType
@@ -1010,7 +1031,7 @@ trait Types {
getRefs(Expansive, tparam)
}
- /* The rest of this class is auxiliary code for <code>expansiveRefs</code>
+ /* The rest of this class is auxiliary code for `expansiveRefs'
*/
/** The type parameters which are referenced type parameters of this class.
@@ -1040,7 +1061,7 @@ trait Types {
}
/** Augment existing refs map with references <pre>from -> sym</pre>, for
- * all elements <pre>sym</pre> of set <code>to</code>.
+ * all elements <pre>sym</pre> of set `to'.
* @param which <- {NonExpansive, Expansive}
*/
private def addRefs(which: int, from: Symbol, to: Set[Symbol]) {
@@ -1056,7 +1077,7 @@ trait Types {
// (this can happen only for erroneous programs).
}
- /** Compute initial (one-step) references and set state to <code>Initializing</code>.
+ /** Compute initial (one-step) references and set state to `Initializing'.
*/
private def computeRefs() {
refs = Array(Map(), Map())
@@ -1139,8 +1160,8 @@ trait Types {
}
/** A class for named types of the form
- * <code>&lt;prefix&gt;.&lt;sym.name&gt;[args]</code>
- * Cannot be created directly; one should always use <code>typeRef</code>
+ * `&lt;prefix&gt;.&lt;sym.name&gt;[args]'
+ * Cannot be created directly; one should always use `typeRef'
* for creation. (@M: Otherwise hashing breaks)
*
* @M: Higher-kinded types are represented as TypeRefs with a symbol that has type parameters, but with args==List()
@@ -1151,7 +1172,7 @@ trait Types {
case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type {
assert(!checkMalformedSwitch || !sym.isAbstractType || pre.isStable || pre.isError)
assert(!pre.isInstanceOf[ClassInfoType], this)
- assert(!sym.isTypeParameterOrSkolem || pre == NoPrefix, this)
+ assert(!(sym hasFlag (PARAM | EXISTENTIAL)) || pre == NoPrefix, this)
private var parentsCache: List[Type] = _
private var parentsPeriod = NoPeriod
@@ -1159,8 +1180,9 @@ trait Types {
private var closurePeriod = NoPeriod
private var closureDepthCache: int = _
- override def isStable: boolean =
+ override def isStable: boolean = {
sym.isAbstractType && (sym.info.bounds.hi.symbol isSubClass SingletonClass)
+ }
override val isTrivial: boolean =
pre.isTrivial && !sym.isTypeParameter && args.forall(_.isTrivial)
@@ -1330,11 +1352,17 @@ A type's symbol should never be inspected directly.
}
override def prefixString =
- if (settings.debug.value) super.prefixString
+ if (settings.debug.value)
+ super.prefixString
else if (sym.isRoot || sym.isEmptyPackageClass || sym.isInterpreterWrapper ||
- sym.isAnonymousClass || sym.isRefinementClass || sym.isScalaPackageClass) ""
- else if (sym.isPackageClass) sym.fullNameString + "."
- else super.prefixString
+ sym.isAnonymousClass || sym.isRefinementClass || sym.isScalaPackageClass)
+ ""
+ else if (sym.isPackageClass)
+ sym.fullNameString + "."
+ else if (isStable && (sym.name.toString endsWith ".type"))
+ sym.name.toString.substring(0, sym.name.length - 4)
+ else
+ super.prefixString
}
/** A class representing a method type with parameters.
@@ -1375,20 +1403,20 @@ A type's symbol should never be inspected directly.
class JavaMethodType(pts: List[Type], rt: Type) extends MethodType(pts, rt)
/** A class containing the commonalities of existential and universal types */
- class QuantifiedType extends Type {
- override def paramSectionCount: int = resultType.paramSectionCount
- override def paramTypes: List[Type] = resultType.paramTypes
- override def finalResultType: Type = resultType.finalResultType
- override def parents: List[Type] = resultType.parents
- override def decls: Scope = resultType.decls
- override def symbol: Symbol = resultType.symbol
- override def prefix: Type = resultType.prefix
- override def closure: Array[Type] = resultType.closure
- override def closureDepth: int = resultType.closureDepth
- override def baseClasses: List[Symbol] = resultType.baseClasses
- override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
- override def narrow: Type = resultType.narrow
- // override def isNullable: boolean = resultType.isNullable;
+ abstract class QuantifiedType extends Type {
+ def quantified: Type
+ override def paramSectionCount: int = quantified.paramSectionCount
+ override def paramTypes: List[Type] = quantified.paramTypes
+ override def parents: List[Type] = quantified.parents
+ override def decls: Scope = quantified.decls
+ override def symbol: Symbol = quantified.symbol
+ override def prefix: Type = quantified.prefix
+ override def closure: Array[Type] = quantified.closure
+ override def closureDepth: int = quantified.closureDepth
+ override def baseClasses: List[Symbol] = quantified.baseClasses
+ override def baseType(clazz: Symbol): Type = quantified.baseType(clazz)
+ override def narrow: Type = quantified.narrow
+ // override def isNullable: boolean = quantified.isNullable;
}
/** A class representing a polymorphic type or, if tparams.length == 0,
@@ -1401,6 +1429,10 @@ A type's symbol should never be inspected directly.
case class PolyType(override val typeParams: List[Symbol], override val resultType: Type)
extends QuantifiedType {
+ def quantified = resultType
+
+ override def finalResultType: Type = resultType.finalResultType
+
/** @M: abstractTypeSig now wraps a TypeBounds in a PolyType
* to represent a higher-kinded type parameter
* wrap lo&hi in polytypes to bind variables
@@ -1422,13 +1454,20 @@ A type's symbol should never be inspected directly.
}
case class ExistentialType(override val typeParams: List[Symbol],
- override val resultType: Type) extends QuantifiedType {
+ val quantified: Type) extends QuantifiedType {
override def bounds: TypeBounds =
- TypeBounds(ExistentialType(typeParams, resultType.bounds.lo),
- ExistentialType(typeParams, resultType.bounds.hi))
+ TypeBounds(ExistentialType(typeParams, quantified.bounds.lo),
+ ExistentialType(typeParams, quantified.bounds.hi))
+
+ override def skolemizeExistential(owner: Symbol) = {
+ val skolems = if (owner == NoSymbol) cloneSymbols(typeParams)
+ else cloneSymbols(typeParams, owner)
+ for (skolem <- skolems) skolem resetFlag PARAM setFlag EXISTENTIAL
+ quantified.substSym(typeParams, skolems)
+ }
override def toString: String =
- resultType+(typeParams map tparamToString mkString(" for_some { ", "; ", " }"))
+ quantified+(typeParams map tparamToString mkString(" for_some { ", "; ", " }"))
private def tparamToString(tparam: Symbol) = {
val tname = tparam.name.toString
@@ -1440,7 +1479,7 @@ A type's symbol should never be inspected directly.
override def cloneInfo(owner: Symbol) = {
val tparams = cloneSymbols(typeParams, owner)
- ExistentialType(tparams, resultType.substSym(typeParams, tparams))
+ ExistentialType(tparams, quantified.substSym(typeParams, tparams))
}
}
@@ -1474,8 +1513,9 @@ A type's symbol should never be inspected directly.
override def symbol = origin.symbol
override def toString: String =
if (constr.inst eq null) "<null " + origin + ">"
- else if (constr.inst eq NoType) "?" + origin
+ else if (constr.inst eq NoType) "?*" + origin
else constr.inst.toString;
+ override def isStable = origin.isStable
}
/** A type carrying some attributes. The attributes have no significance
@@ -1528,8 +1568,8 @@ A type's symbol should never be inspected directly.
// Creators ---------------------------------------------------------------
- /** Rebind symbol <code>sym</code> to an overriding member in type
- * <code>pre</code>.
+ /** Rebind symbol `sym' to an overriding member in type
+ * `pre'.
*/
private def rebind(pre: Type, sym: Symbol): Symbol = {
val owner = sym.owner
@@ -1540,7 +1580,7 @@ A type's symbol should never be inspected directly.
} else sym
}
- /** Convert a <code>super</code> prefix to a this-type if <code>sym</code>
+ /** Convert a `super' prefix to a this-type if `sym'
* is abstract or final.
*/
private def removeSuper(tp: Type, sym: Symbol): Type = tp match {
@@ -1778,16 +1818,16 @@ A type's symbol should never be inspected directly.
/** Remove any occurrence of type <singleton> from this type and its parents */
private object dropSingletonType extends TypeMap {
def apply(tp: Type): Type = {
- mapOver(tp) match {
+ tp match {
case TypeRef(_, sym, _) if (sym == SingletonClass) =>
AnyClass.tpe
case tp1 @ RefinedType(parents, decls) =>
var parents1 = parents filter (_.symbol != SingletonClass)
if (parents1.isEmpty) parents1 = List(AnyClass.tpe)
- if (parents1.tail.isEmpty && decls.isEmpty) parents1.head
- else copyRefinedType(tp1, parents1, decls)
+ if (parents1.tail.isEmpty && decls.isEmpty) mapOver(parents1.head)
+ else mapOver(copyRefinedType(tp1, parents1, decls))
case tp1 =>
- tp1
+ mapOver(tp1)
}
}
}
@@ -2080,7 +2120,7 @@ A type's symbol should never be inspected directly.
/** A base class to compute all substitutions */
abstract class SubstMap[T](from: List[Symbol], to: List[T]) extends TypeMap {
- /** Are <code>sym</code> and <code>sym1</code> the same.
+ /** Are `sym' and `sym1' the same.
* Can be tuned by subclasses.
*/
protected def matches(sym: Symbol, sym1: Symbol): boolean = sym eq sym1
@@ -2131,7 +2171,7 @@ A type's symbol should never be inspected directly.
}
}
- /** A map to implement the <code>substSym</code> method. */
+ /** 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 {
@@ -2155,13 +2195,13 @@ A type's symbol should never be inspected directly.
}
}
- /** A map to implement the <code>subst</code> method. */
+ /** 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
}
- /** A map to implement the <code>substThis</code> method. */
+ /** 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
@@ -2206,7 +2246,7 @@ A type's symbol should never be inspected directly.
}
}
- /** A map to implement the <code>contains</code> method */
+ /** A map to implement the `contains' method */
class ContainsTraverser(sym: Symbol) extends TypeTraverser {
var result = false
def traverse(tp: Type): ContainsTraverser = {
@@ -2221,7 +2261,7 @@ A type's symbol should never be inspected directly.
}
}
- /** A map to implement the <code>contains</code> method */
+ /** A map to implement the `contains' method */
class ContainsTypeTraverser(t: Type) extends TypeTraverser {
var result = false
def traverse(tp: Type): ContainsTypeTraverser = {
@@ -2233,7 +2273,29 @@ A type's symbol should never be inspected directly.
}
}
- /** A map to implement the <code>contains</code> method */
+ /** A map to implement the `filter' method */
+ class FilterTraverser(p: Type => boolean) extends TypeTraverser {
+ val hits = new ListBuffer[Type]
+ def traverse(tp: Type): FilterTraverser = {
+ if (p(tp)) hits += tp
+ mapOver(tp)
+ this
+ }
+ }
+
+ /** A map to implement the `filter' method */
+ class FindTraverser(p: Type => boolean) extends TypeTraverser {
+ var result: Option[Type] = None
+ def traverse(tp: Type): FindTraverser = {
+ if (result.isEmpty) {
+ if (p(tp)) result = Some(tp)
+ mapOver(tp)
+ }
+ this
+ }
+ }
+
+ /** A map to implement the `contains' method */
object ErroneousTraverser extends TypeTraverser {
var result: boolean = _
def traverse(tp: Type): TypeTraverser = {
@@ -2428,11 +2490,11 @@ A type's symbol should never be inspected directly.
}
}
- /** Do <code>tp1</code> and <code>tp2</code> denote equivalent types?
+ /** Do `tp1' and `tp2' denote equivalent types?
*
* @param tp1 ...
* @param tp2 ...
- * @return true, iff <code>tp1</code> and <code>tp2</code> denote
+ * @return true, iff `tp1' and `tp2' denote
* equivalent types.
*/
def isSameType(tp1: Type, tp2: Type): boolean = {
@@ -2527,7 +2589,7 @@ A type's symbol should never be inspected directly.
((tp1n ne tp1) || (tp2n ne tp2)) && isSameType(tp1n, tp2n)
}
- /** Are <code>tps1</code> and <code>tps2</code> lists of pairwise equivalent
+ /** Are `tps1' and `tps2' lists of pairwise equivalent
* types?
*/
def isSameTypes(tps1: List[Type], tps2: List[Type]): boolean =
@@ -2561,7 +2623,7 @@ A type's symbol should never be inspected directly.
/** hook for IDE */
protected def trackTypeIDE(sym : Symbol) : Boolean = true;
- /** Does type <code>tp1</code> conform to <code>tp2</code>?
+ /** Does type `tp1' conform to `tp2'?
*
* @param tp1 ...
* @param tp2 ...
@@ -2668,8 +2730,8 @@ A type's symbol should never be inspected directly.
solve(tvars, tparams2, tparams2 map (x => 0), false)
isWithinBounds(NoPrefix, NoSymbol, tparams2, tvars map (_.constr.inst))
}
- case (ExistentialType(tparams1, res1), _) =>
- res1 <:< tp2
+ case (ExistentialType(_, _), _) =>
+ tp1.skolemizeExistential(NoSymbol) <:< tp2
/* todo: replace following with
case (ThisType(_), _)
@@ -2699,16 +2761,16 @@ A type's symbol should never be inspected directly.
((tp1n ne tp1) || (tp2n ne tp2)) && isSubType0(tp1n, tp2n)
}
- /** Are <code>tps1</code> and <code>tps2</code> lists of equal length such
- * that all elements of <code>tps1</code> conform to corresponding elements
- * of <code>tps2</code>?
+ /** 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.length == tps2.length &&
List.forall2(tps1, tps2)((tp1, tp2) => tp1 <:< tp2)
- /** Does type <code>tp</code> implement symbol <code>sym</code> with same or
- * stronger type? Exact only if <code>sym</code> is a member of some
+ /** 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 =
@@ -2717,8 +2779,8 @@ A type's symbol should never be inspected directly.
(tp.nonPrivateMember(sym.name).alternatives exists
(alt => sym == alt || specializesSym(tp.narrow, alt, sym.owner.thisType, sym)))
- /** Does member <code>sym1</code> of <code>tp1</code> have a stronger type
- * than member <code>sym2</code> of <code>tp2</code>?
+ /** 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)
@@ -2729,7 +2791,7 @@ A type's symbol should never be inspected directly.
sym2.isAliasType && tp2.memberType(sym2).substThis(tp2.symbol, tp1) =:= tp1.memberType(sym1) //@MAT ok
}
- /** A function implementing <code>tp1</code> matches <code>tp2</code> */
+ /** A function implementing `tp1' matches `tp2' */
private def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: boolean): boolean = (tp1, tp2) match {
case (MethodType(pts1, res1), MethodType(pts2, res2)) =>
matchingParams(pts1, pts2, tp2.isInstanceOf[JavaMethodType]) &&
@@ -2754,14 +2816,14 @@ A type's symbol should never be inspected directly.
alwaysMatchSimple || tp1 =:= tp2
}
- /** Are <code>tps1</code> and <code>tps2</code> lists of pairwise equivalent types? */
+ /** Are `tps1' and `tps2' lists of pairwise equivalent types? */
private def matchingParams(tps1: List[Type], tps2: List[Type], tps2isJava: boolean): boolean = (
tps1.length == tps2.length &&
List.forall2(tps1, tps2)((tp1, tp2) =>
(tp1 =:= tp2) || tps2isJava & tp1.symbol == ObjectClass && tp2.symbol == AnyClass)
);
- /** Prepend type <code>tp</code> to closure <code>cl</code>.
+ /** Prepend type `tp' to closure `cl'.
*
* @param tp ...
* @param cl ...
@@ -2783,7 +2845,7 @@ A type's symbol should never be inspected directly.
}
/** like map2, but returns list `xs' itself - instead of a copy - if function
- * <code>f</code> maps all elements to themselves.
+ * `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
@@ -2794,13 +2856,13 @@ A type's symbol should never be inspected directly.
else x1 :: xs1
}
- /** Solve constraint collected in types <code>tvars</code>.
+ /** Solve constraint collected in types `tvars'.
*
* @param tvars All type variables to be instantiated.
- * @param tparams The type parameters corresponding to <code>tvars</code>
+ * @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 <code>true</code> search for max solution else min.
+ * @param upper When `true' search for max solution else min.
* @throws NoInstance
*/
def solve(tvars: List[TypeVar], tparams: List[Symbol],
@@ -2853,8 +2915,8 @@ A type's symbol should never be inspected directly.
solveOne(tvar, tparam, variance)
}
- /** Do type arguments <code>targs</code> conform to formal parameters
- * <code>tparams</code>?
+ /** Do type arguments `targs' conform to formal parameters
+ * `tparams'?
*
* @param tparams ...
* @param targs ...
@@ -3185,10 +3247,10 @@ A type's symbol should never be inspected directly.
}
/** Compute lub (if variance == 1) or glb (if variance == -1) of given list
- * of types <code>tps</code>. All types in `tps' are typerefs or singletypes
+ * of types `tps'. All types in `tps' are typerefs or singletypes
* with the same symbol.
- * Return <code>Some(x)</code> if the computation succeeds with result `x'.
- * Return <code>None</code> if the computuation fails.
+ * Return `Some(x)' if the computation succeeds with result `x'.
+ * Return `None' if the computuation fails.
*/
private def mergePrefixAndArgs(tps: List[Type], variance: int, depth: int): Option[Type] = tps match {
case List(tp) =>
@@ -3227,8 +3289,8 @@ A type's symbol should never be inspected directly.
}
}
- /** Make symbol <code>sym</code> a member of scope <code>tp.decls</code>
- * where <code>thistp</code> is the narrowed owner type of the scope.
+ /** 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): unit = {
assert(sym != NoSymbol)
@@ -3305,8 +3367,8 @@ A type's symbol should never be inspected directly.
/** The current indentation string for traces */
private var indent: String = ""
- /** Perform operation <code>p</code> on arguments <code>tp1</code>,
- * <code>arg2</code> and print trace of computation.
+ /** 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 + "?")
@@ -3317,8 +3379,8 @@ A type's symbol should never be inspected directly.
result
}
- /** If option <code>explaintypes</code> is set, print a subtype trace for
- * <code>found &lt;: required</code>.
+ /** If option `explaintypes' is set, print a subtype trace for
+ * `found <:< required'.
*
* @param found ...
* @param required ...
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 63445b714c..415b2da6d7 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -860,6 +860,13 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
//Console.println("checking no dble defs " + tree)//DEBUG
checkNoDoubleDefs(tree.symbol.owner)
copy.Template(tree, parents, emptyValDef, addBridges(body, currentOwner))
+
+ case Pack(expr) =>
+ expr
+
+ case Unpack(expr) =>
+ expr
+
case _ =>
tree
}
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index aba9a20229..317146de97 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -373,6 +373,29 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
sym setFlag notPROTECTED
super.transform(tree)
+ case Pack(expr) =>
+ super.transform(expr)
+
+ case Unpack(expr) =>
+ super.transform(expr setType tree.tpe)
+ // Martin to Lex: it seems we need to eliminate unpacks already here,
+ // rather than in erasure, which would be more logical, because
+ // otherwise Unpacks survive to later phases when run in the interpreter.
+ // Why is this? Does the interpreter skip erasure in some circumstances?
+ // Here's the example that fails when we remove the clause here":
+ //
+ // scala
+ // scala> case class Cell[T](x: T)
+ // scala> var x: Cell[T] for_some { type T } = new Cell(1)
+ // scala> x = new Cell("abc")
+ // (failure in genicode which complains about:
+ // Exception in thread "main" java.lang.Error: Unexpected tree in genLoad: unpack({
+ // line2$object$$iw$$iw.x_=(new line1$object$$iw$$iw$Cell("abc"));
+ // line2$object$$iw$$iw.x()
+ // })
+ //
+ // If I run the same with nsc (see existentials.scala), it works.
+
case Apply(sel @ Select(qual, name), args)
if (name == nme.CONSTRUCTOR && isInner(sel.symbol.owner)) =>
val outerVal = atPos(tree.pos) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 2ea69a2914..944d271d1d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -26,13 +26,9 @@ trait Namers { self: Analyzer =>
*/
class DeSkolemizeMap(tparams: List[Symbol]) extends TypeMap {
def apply(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) =>
- val tparam = sym.deSkolemize
- mapOver(
- if (tparam == sym || !(tparams contains tparam)) tp
- else rawTypeRef(NoPrefix, tparam, args))
- case SingleType(pre, sym) if (sym.isThisSkolem) =>
- mkThisType(sym.deSkolemize)
+ case TypeRef(pre, sym, args)
+ if (sym.isTypeSkolem && (tparams contains sym.deSkolemize)) =>
+ mapOver(rawTypeRef(NoPrefix, sym.deSkolemize, args))
case PolyType(tparams1, restpe) =>
new DeSkolemizeMap(tparams1 ::: tparams).mapOver(tp)
case ClassInfoType(parents, decls, clazz) =>
@@ -774,6 +770,7 @@ trait Namers { self: Analyzer =>
context.error(sym.pos, "pass-by-name arguments not allowed for case class parameters");
if ((sym.flags & DEFERRED) != 0) {
if (!sym.isValueParameter && !sym.isTypeParameterOrSkolem &&
+ !context.tree.isInstanceOf[ExistentialTypeTree] &&
(!sym.owner.isClass || sym.owner.isModuleClass || sym.owner.isAnonymousClass)) {
context.error(sym.pos,
"only classes can have declared but undefined members" + varNotice(sym))
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 8fc956715b..fb32cdcec1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -38,10 +38,11 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
class SuperAccTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
private var validCurrentOwner = true
private var accDefs: List[(Symbol, ListBuffer[Tree])] = List()
+ private val typer = analyzer.newTyper(analyzer.rootContext(unit))
private def accDefBuf(clazz: Symbol) =
accDefs.dropWhile(_._1 != clazz).head._2
-
+/*
private def transformArgs(args: List[Tree], formals: List[Type]) = {
if (!formals.isEmpty && formals.last.symbol == definitions.ByNameParamClass)
((args take (formals.length - 1) map transform) :::
@@ -49,6 +50,24 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
else
args map transform
}
+*/
+ private def transformArgs(args: List[Tree], formals: List[Type]) =
+ List.map2(args, formals){ (arg, formal) =>
+ if (formal.symbol == definitions.ByNameParamClass)
+ withInvalidOwner { checkPackedConforms(transform(arg), formal.typeArgs.head) }
+ else transform(arg)
+ } :::
+ (args drop formals.length map transform)
+
+ private def checkPackedConforms(tree: Tree, pt: Type): Tree = {
+ if (tree.tpe exists (_.symbol.isExistentialSkolem)) {
+ val packed = typer.typed(Pack(tree) setPos tree.pos)
+ println("packed: "+packed+":"+packed.tpe+", pt = "+pt)
+ if (!(packed.tpe <:< pt))
+ typer.infer.typeError(tree.pos, packed.tpe, pt)
+ }
+ tree
+ }
override def transform(tree: Tree): Tree = tree match {
case ClassDef(_, _, _, _) =>
@@ -301,7 +320,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
if (host.thisSym != host) {
if (host.thisSym.tpe.symbol.hasFlag(JAVA) || currentOwner.enclClass.isTrait)
unit.error(pos, "Implementation restriction: " + currentOwner.enclClass + " accesses protected "
- + sym + " from 'required' " + host.thisSym.tpe)
+ + sym + " from self type " + host.thisSym.tpe)
false
} else res
} else res
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 468a2c1924..201f53be70 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -338,21 +338,15 @@ trait Typers { self: Analyzer =>
this.owner = owner
this.scope = scope
hiddenSymbols = List()
- apply(tree.tpe)
- if (hiddenSymbols.isEmpty) tree
+ val tp1 = apply(tree.tpe)
+ if (hiddenSymbols.isEmpty) tree setType tp1
else if (hiddenSymbols exists (_.isErroneous)) setError(tree)
else if (isFullyDefined(pt)) tree setType pt //todo: eliminate
- else if (tree.tpe.symbol.isAnonymousClass) // todo: eliminate
- check(owner, scope, pt, tree setType anonymousClassRefinement(tree.tpe.symbol))
- else if (owner == NoSymbol) { // locals
- val (tparams, tp1) = existentialTransform(hiddenSymbols.reverse, tree.tpe)
-// Console.println("original type: "+tree.tpe)
-// Console.println("exist params : "+tparams)
-// Console.println("replaced type: "+tp1)
- tree setType existentialAbstraction(tparams, tp1)
-// Console.println("abstracted type: "+tree.tpe)
-// tree
- } else { // privates
+ else if (tp1.symbol.isAnonymousClass) // todo: eliminate
+ check(owner, scope, pt, tree setType anonymousClassRefinement(tp1.symbol))
+ else if (owner == NoSymbol)
+ tree setType packSymbols(hiddenSymbols.reverse, tp1)
+ else { // privates
val badSymbol = hiddenSymbols.head
error(tree.pos,
(if (badSymbol hasFlag PRIVATE) "private " else "") + badSymbol +
@@ -386,12 +380,21 @@ trait Typers { self: Analyzer =>
}
}
}
- t match {
- case TypeRef(_, sym, _) => checkNoEscape(sym)
- case SingleType(_, sym) => checkNoEscape(sym)
- case _ =>
- }
- mapOver(t)
+ mapOver(
+ t match {
+ case TypeRef(_, sym, args) =>
+ checkNoEscape(sym)
+ if (!hiddenSymbols.isEmpty && hiddenSymbols.head == sym &&
+ sym.isAliasType && sym.typeParams.length == args.length) {
+ hiddenSymbols = hiddenSymbols.tail
+ t.normalize
+ } else t
+ case SingleType(_, sym) =>
+ checkNoEscape(sym)
+ t
+ case _ =>
+ t
+ })
}
}
@@ -1253,7 +1256,8 @@ trait Typers { self: Analyzer =>
val expr1 = typed(block.expr, mode & ~(FUNmode | QUALmode), pt)
val block1 = copy.Block(block, stats1, expr1)
.setType(if (treeInfo.isPureExpr(block)) expr1.tpe else expr1.tpe.deconst)
- checkNoEscaping.locals(context.scope, pt, block1)
+ //checkNoEscaping.locals(context.scope, pt, block1)
+ block1
}
/**
@@ -1279,7 +1283,7 @@ trait Typers { self: Analyzer =>
}
}
}
- body1 = checkNoEscaping.locals(context.scope, pt, body1)
+// body1 = checkNoEscaping.locals(context.scope, pt, body1)
copy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe
}
@@ -1340,15 +1344,15 @@ trait Typers { self: Analyzer =>
if (inIDE) // HACK to process arguments types in IDE.
typedFunctionIDE(fun, context);
val vparams = List.mapConserve(fun.vparams)(typedValDef)
- for (vparam <- vparams) {
- checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); ()
- }
- val body = checkNoEscaping.locals(context.scope, respt, typed(fun.body, respt))
+// for (val vparam <- vparams) {
+// checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); ()
+// }
+ var body = pack(typed(fun.body, respt), fun.symbol)
val formals = vparamSyms map (_.tpe)
val restpe = body.tpe.deconst
val funtpe = typeRef(clazz.tpe.prefix, clazz, formals ::: List(restpe))
- val fun1 = copy.Function(fun, vparams, checkNoEscaping.locals(context.scope, restpe, body))
- .setType(funtpe)
+// body = checkNoEscaping.locals(context.scope, restpe, body)
+ val fun1 = copy.Function(fun, vparams, body).setType(funtpe)
if (codeExpected) {
val liftPoint = Apply(Select(Ident(CodeModule), nme.lift_), List(fun1))
typed(atPos(fun.pos)(liftPoint))
@@ -1709,21 +1713,77 @@ trait Typers { self: Analyzer =>
*/
protected def existentialTransform(rawSyms: List[Symbol], tp: Type) = {
val typeParams = rawSyms map { sym =>
- if (sym.isType) sym.cloneSymbol
- else sym.owner.newAbstractType(sym.pos, newTermName(sym.name+".Type"))//todo: change to .type
- .setInfo(mkTypeBounds(AllClass.tpe, sym.tpe))
+ val (name, bound) =
+ if (sym.isClass)
+ (sym.name,
+ mkTypeBounds(AllClass.tpe, anonymousClassRefinement(sym)))
+ else if (sym.isAbstractType)
+ (sym.name,
+ sym.info)
+ else if (sym.isTerm)
+ (newTypeName(sym.name+".type"),
+ mkTypeBounds(AllClass.tpe, intersectionType(List(sym.tpe, SingletonClass.tpe))))
+ else
+ throw new Error("unexpected alias type: "+sym)
+ sym.owner.newAbstractType(sym.pos, name) setFlag EXISTENTIAL setInfo bound
}
val typeParamTypes = typeParams map (_.tpe)
for (tparam <- typeParams) tparam.setInfo(tparam.info.subst(rawSyms, typeParamTypes))
(typeParams, tp.subst(rawSyms, typeParamTypes))
}
+ /** Compute an existential type from raw hidden symbols `syms' and type `tp'
+ */
+ def packSymbols(hidden: List[Symbol], tp: Type) =
+ if (hidden.isEmpty) tp
+ else {
+// Console.println("original type: "+tp)
+// Console.println("hidden symbols: "+hidden)
+ val (tparams, tp1) = existentialTransform(hidden, tp)
+// Console.println("tparams: "+tparams+", result: "+tp1)
+ val res = existentialAbstraction(tparams, tp1)
+// Console.println("final result: "+res)
+ res
+ }
+
+ protected def pack(tree: Tree, owner: Symbol): Tree = {
+ def isAnonymousFunction(sym: Symbol) =
+ (sym hasFlag SYNTHETIC) && (sym.name == nme.ANON_FUN_NAME)
+ def isVisibleParameter(sym: Symbol) =
+ (sym hasFlag PARAM) && (sym.owner == owner) && (sym.isType || !isAnonymousFunction(owner))
+ object collectLocals extends TypeMap {
+ var symbols: List[Symbol] = List()
+ def apply(tp: Type) = {
+ tp match {
+ case TypeRef(_, _, _) | SingleType(_, _) =>
+ val sym = tp.symbol
+ if (sym hasFlag PACKAGE) tp
+ else {
+ var o = sym.owner
+ while (o != owner && !(o hasFlag PACKAGE)) o = o.owner
+ if (o == owner && !isVisibleParameter(sym) && !(symbols contains sym))
+ symbols = sym :: symbols
+ mapOver(tp)
+ }
+ case _ =>
+ mapOver(tp)
+ }
+ }
+ }
+ collectLocals(tree.tpe)
+ val hidden = collectLocals.symbols.reverse
+ if (hidden.isEmpty) tree
+ else Pack(tree) setType packSymbols(hidden, tree.tpe)
+ }
+
protected def typedExistentialTypeTree(tree: ExistentialTypeTree): Tree = {
- namer.enterSyms(tree.whereClauses)
- val whereClauses1 = typedStats(tree.whereClauses, NoSymbol)
+ for (val wc <- tree.whereClauses)
+ if (wc.symbol == NoSymbol) { namer.enterSym(wc); wc.symbol setFlag EXISTENTIAL }
+ else context.scope enter wc.symbol
+ val whereClauses1 = typedStats(tree.whereClauses, context.owner)
val tpt1 = typedType(tree.tpt)
val (typeParams, tpe) = existentialTransform(tree.whereClauses map (_.symbol), tpt1.tpe)
- copy.ExistentialTypeTree(tree, tpt1, whereClauses1).setType(ExistentialType(typeParams, tpe))
+ TypeTree(ExistentialType(typeParams, tpe)) setOriginal tree
}
/**
@@ -1838,7 +1898,10 @@ trait Typers { self: Analyzer =>
val rhs1 = typed(rhs, lhs1.tpe)
copy.Assign(tree, lhs1, checkDead(rhs1)) setType UnitClass.tpe
} else {
- if (!lhs1.tpe.isError) error(tree.pos, "assignment to non-variable ")
+ if (!lhs1.tpe.isError) {
+ println(lhs1+" = "+rhs)
+ error(tree.pos, "assignment to non-variable ")
+ }
setError(tree)
}
}
@@ -2533,6 +2596,19 @@ trait Typers { self: Analyzer =>
val expr1 = typed(expr, ThrowableClass.tpe)
copy.Throw(tree, expr1) setType AllClass.tpe
+ case Pack(expr) =>
+ val expr1 = typed1(expr, mode, pt)
+ val skolems = new ListBuffer[Symbol]
+ for (val unpacked @ Unpack(expr) <- expr filter (_.isInstanceOf[Unpack])) {
+ skolems ++= (unpacked.tpe.exskolems diff expr.tpe.exskolems)
+ }
+ val packed = packSymbols(skolems.toList.removeDuplicates, expr.tpe)
+ copy.Pack(tree, expr1) setType packed
+
+ case Unpack(expr) =>
+ val expr1 = typed1(expr, mode, pt)
+ copy.Unpack(tree, expr1) setType expr1.tpe.skolemizeExistential(context.owner)
+
case New(tpt: Tree) =>
typedNew(tpt)
@@ -2681,11 +2757,20 @@ trait Typers { self: Analyzer =>
if (tree.hasSymbol) tree.symbol = NoSymbol
}
//Console.println("typing "+tree+", "+context.undetparams);//DEBUG
- val tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, pt)
+ def dropExistential(tp: Type) = tp match {
+ case ExistentialType(tparams, tpe) =>
+ if (settings.debug.value) println("drop ex "+tree+" "+tp)
+ tpe.subst(tparams, tparams map (x => WildcardType))
+ case _ => tp
+ }
+ var tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, dropExistential(pt))
//Console.println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams);//DEBUG
-
+ if ((mode & (EXPRmode | LHSmode)) == EXPRmode && tree1.tpe.isInstanceOf[ExistentialType])
+ tree1 = Unpack(tree1) setPos tree1.pos setType tree1.tpe.skolemizeExistential(context.owner)
+ //Console.println("skolemized "+tree1+":"+tree1.tpe);//DEBUG
val result = if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt)
//Console.println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams);//DEBUG
+// if ((mode & TYPEmode) != 0) println("type: "+tree1+" has type "+tree1.tpe)
result
} catch {
case ex: TypeError =>
@@ -2765,7 +2850,7 @@ trait Typers { self: Analyzer =>
}
def computeType(tree: Tree, pt: Type): Type = {
- val tree1 = typed(tree, pt)
+ val tree1 = pack(typed(tree, pt), context.owner)
transformed(tree) = tree1
tree1.tpe
}