diff options
author | Martin Odersky <odersky@gmail.com> | 2009-10-02 13:19:34 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-10-02 13:19:34 +0000 |
commit | 321338da04a6ca9bcc9b77ae663ed27f26a67d85 (patch) | |
tree | 4cea0a435568b760b688740f5d559a4033cf7962 /src | |
parent | 1bc50a7c84b0abc53299b3efcfec4f6a77c759e6 (diff) | |
download | scala-321338da04a6ca9bcc9b77ae663ed27f26a67d85.tar.gz scala-321338da04a6ca9bcc9b77ae663ed27f26a67d85.tar.bz2 scala-321338da04a6ca9bcc9b77ae663ed27f26a67d85.zip |
Fixed #1939,plus some moving things around.
Diffstat (limited to 'src')
5 files changed, 50 insertions, 41 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 4aea770ff4..9dfe0777ef 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -36,6 +36,12 @@ trait Symbols { /** Used to keep track of the recursion depth on locked symbols */ private var recursionTable = Map.empty[Symbol, Int] + private var nextexid = 0 + private def freshExistentialName() = { + nextexid += 1 + "_"+nextexid + } + /* type Position; def NoPos : Position; @@ -252,6 +258,19 @@ trait Symbols { argtypess map (_.map(param)) } + /** Make an existential variable. + * @param name suffix to be appended to the freshly generated name + * It's ususally "", except for type variables abstracting + * over values, where it is ".type". + * @param owner The owner of the variable + * @param bounds The variable's bounds + */ + final def newExistential(pos: Position, name: Name): Symbol = + newAbstractType(pos, name.toTypeName).setFlag(EXISTENTIAL) + + final def freshExistential(suffix: String): Symbol = + newExistential(pos, freshExistentialName()+suffix) + /** Synthetic value parameters when parameter symbols are not available. * Calling this method multiple times will re-use the same parameter names. */ diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 157ead1f35..9fdb446ad8 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -77,6 +77,8 @@ trait Types { private var explainSwitch = false + private final val alternativeNarrow = false + private final val LogPendingSubTypesThreshold = 50 private final val LogPendingBaseTypesThreshold = 50 @@ -270,7 +272,10 @@ trait Types { */ def narrow: Type = if (phase.erasedTypes) this - else { + else if (alternativeNarrow) { // investigate why this does not work! + val tparam = commonOwner(this) freshExistential ".type" setInfo singletonBounds(this) + tparam.tpe + } else { val cowner = commonOwner(this) refinedType(List(this), cowner, EmptyScope, cowner.pos).narrow } @@ -2687,26 +2692,9 @@ A type's typeSymbol should never be inspected directly. private val emptySymMap = scala.collection.immutable.Map[Symbol, Symbol]() private val emptySymCount = scala.collection.immutable.Map[Symbol, Int]() - /** Make an existential variable. - * [martin:] this should get moved to Symbols where the other symbols are created. - * @param name suffix to be appended to the freshly generated name - * It's ususally "", except for type variables abstracting - * over values, where it is ".type". - * @param owner The owner of the variable - * @param bounds The variable's bounds - */ - def makeExistential(name: String, owner: Symbol, bounds: TypeBounds): Symbol = - recycle( - owner.newAbstractType(owner.pos, newTypeName(name)).setFlag(EXISTENTIAL) - ).setInfo(bounds) - - /** Make an existential variable with a fresh name. */ - def makeFreshExistential(suffix: String, owner: Symbol, bounds: TypeBounds): Symbol = - makeExistential(freshName()+suffix, owner, bounds) - def typeParamsToExistentials(clazz: Symbol, tparams: List[Symbol]): List[Symbol] = { val eparams = for ((tparam, i) <- tparams.zipWithIndex) yield { - makeExistential("?"+i, clazz, tparam.info.bounds) + clazz.newExistential(clazz.pos, "?"+i).setInfo(tparam.info.bounds) } for (tparam <- eparams) tparam setInfo tparam.info.substSym(tparams, eparams) eparams @@ -2787,7 +2775,7 @@ A type's typeSymbol should never be inspected directly. def stabilize(pre: Type, clazz: Symbol): Type = { capturedPre get clazz match { case None => - val qvar = makeFreshExistential(".type", clazz, singletonBounds(pre)) + val qvar = clazz freshExistential ".type" setInfo singletonBounds(pre) capturedPre += (clazz -> qvar) capturedParams = qvar :: capturedParams qvar @@ -3061,13 +3049,9 @@ A type's typeSymbol should never be inspected directly. val symowner = oldSym.owner // what should be used?? val bound = singletonBounds(actuals(actualIdx)) - val sym = - symowner.newAbstractType(oldSym.pos, oldSym.name+".type") - + val sym = symowner.newExistential(oldSym.pos, oldSym.name+".type") sym.setInfo(bound) sym.setFlag(oldSym.flags) - sym.setFlag(EXISTENTIAL) - existSyms = existSyms + (actualIdx -> sym) sym @@ -3360,12 +3344,6 @@ A type's typeSymbol should never be inspected directly. // Helper Methods ------------------------------------------------------------- - private var nextid = 0 - private def freshName() = { - nextid += 1 - "_"+nextid - } - final val LubGlbMargin = 0 /** The maximum allowable depth of lubs or glbs over types `ts' @@ -3502,7 +3480,7 @@ A type's typeSymbol should never be inspected directly. private var subsametypeRecursions: Int = 0 private def isUnifiable(pre1: Type, pre2: Type) = - (beginsWithTypeVar(pre1) || beginsWithTypeVar(pre2)) && (pre1 =:= pre2) + (beginsWithTypeVarOrIsRefined(pre1) || beginsWithTypeVarOrIsRefined(pre2)) && (pre1 =:= pre2) private def equalSymsAndPrefixes(sym1: Symbol, pre1: Type, sym2: Symbol, pre2: Type): Boolean = if (sym1 == sym2) phase.erasedTypes || pre1 =:= pre2 @@ -3700,12 +3678,18 @@ A type's typeSymbol should never be inspected directly. if (subsametypeRecursions == 0) undoLog = List() } - /** Does this type have a prefix that begins with a type variable */ - def beginsWithTypeVar(tp: Type): Boolean = tp match { + /** Does this type have a prefix that begins with a type variable, + * or is it a refinement type? For type prefixes that fulfil this condition, + * type selections with the same name of equal (wrt) =:= prefixes are + * considered equal wrt =:= + */ + def beginsWithTypeVarOrIsRefined(tp: Type): Boolean = tp match { case SingleType(pre, sym) => - !(sym hasFlag PACKAGE) && beginsWithTypeVar(pre) + !(sym hasFlag PACKAGE) && beginsWithTypeVarOrIsRefined(pre) case TypeVar(_, constr) => - constr.inst == NoType || beginsWithTypeVar(constr.inst) + constr.inst == NoType || beginsWithTypeVarOrIsRefined(constr.inst) + case RefinedType(_, _) => + true case _ => false } @@ -4657,8 +4641,7 @@ A type's typeSymbol should never be inspected directly. else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we // just err on the conservative side, i.e. with a bound that is too high. // if(!(tparam.info.bounds contains tparam)){ //@M can't deal with f-bounds, see #2251 - val owner = commonOwner(as) - val qvar = makeFreshExistential("", commonOwner(as), mkTypeBounds(g, l)) + val qvar = commonOwner(as) freshExistential "" setInfo mkTypeBounds(g, l) capturedParams += qvar qvar.tpe } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 904983a80f..c4283652ec 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -608,7 +608,7 @@ abstract class ClassfileParser { case '*' => mkTypeBounds(definitions.NothingClass.tpe, definitions.AnyClass.tpe) } - val newtparam = makeExistential("?"+i, sym, bounds) + val newtparam = sym.newExistential(sym.pos, "?"+i) setInfo bounds existentials += newtparam xs += newtparam.tpe i += 1 diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala index cad86ea024..6cf9020520 100644 --- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala +++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala @@ -172,7 +172,14 @@ abstract class OverridingPairs { do { do { nextEntry = decls.lookupNextEntry(nextEntry); - } while ((nextEntry ne null) && + /* DEBUG + if ((nextEntry ne null) && + !(nextEntry.sym hasFlag PRIVATE) && + !(overriding.owner == nextEntry.sym.owner) && + !matches(overriding, nextEntry.sym)) + println("skipping "+overriding+":"+self.memberType(overriding)+overriding.locationString+" to "+nextEntry.sym+":"+self.memberType(nextEntry.sym)+nextEntry.sym.locationString) + */ + } while ((nextEntry ne null) && ((nextEntry.sym hasFlag PRIVATE) || (overriding.owner == nextEntry.sym.owner) || (!matches(overriding, nextEntry.sym)) || diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 030028fcf6..52f4952060 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3589,7 +3589,7 @@ trait Typers { self: Analyzer => def subArrayType(pt: Type) = if (isValueClass(pt.typeSymbol) || !isFullyDefined(pt)) arrayType(pt) else { - val tparam = makeFreshExistential("", context.owner, TypeBounds(NothingClass.tpe, pt)) + val tparam = context.owner freshExistential "" setInfo TypeBounds(NothingClass.tpe, pt) ExistentialType(List(tparam), arrayType(tparam.tpe)) } val (expr1, baseClass) = |