diff options
author | Martin Odersky <odersky@gmail.com> | 2007-06-09 13:03:55 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2007-06-09 13:03:55 +0000 |
commit | 8414ebada9615aac0e8b436e7bdbeee5986ccaa3 (patch) | |
tree | f62c23aec3d9f49446aebd76963667be8468f48d /src/compiler | |
parent | 6ad83dae6960a78d6014c6fcfee1889a322ad5d7 (diff) | |
download | scala-8414ebada9615aac0e8b436e7bdbeee5986ccaa3.tar.gz scala-8414ebada9615aac0e8b436e7bdbeee5986ccaa3.tar.bz2 scala-8414ebada9615aac0e8b436e7bdbeee5986ccaa3.zip |
added existential types
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/Interpreter.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/NodePrinters.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreePrinters.scala | 10 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/Trees.scala | 56 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Flags.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 30 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 256 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala | 23 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 11 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala | 23 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 159 |
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 <prefix>.<sym.name>.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><parents_0> with ... with <parents_n> { decls }</code> + * `<parents_0> with ... with <parents_n> { 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><prefix>.<sym.name>[args]</code> - * Cannot be created directly; one should always use <code>typeRef</code> + * `<prefix>.<sym.name>[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 <: 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 } |