From 59eea769bbd4b5779b4df5e7c6751b7302dd753c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 18 Nov 2005 14:49:18 +0000 Subject: *** empty log message *** --- sources/scala/tools/nsc/symtab/Symbols.scala | 163 +++++++++++---------- sources/scala/tools/nsc/symtab/Types.scala | 28 ++++ sources/scala/tools/nsc/transform/Mixin.scala | 11 +- sources/scala/tools/nsc/typechecker/Contexts.scala | 24 ++- sources/scala/tools/nsc/typechecker/Infer.scala | 25 +--- sources/scala/tools/nsc/typechecker/Namers.scala | 6 +- sources/scala/tools/nsc/typechecker/Typers.scala | 8 +- 7 files changed, 155 insertions(+), 110 deletions(-) (limited to 'sources') diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala index 41c7cd12e8..3437459c15 100755 --- a/sources/scala/tools/nsc/symtab/Symbols.scala +++ b/sources/scala/tools/nsc/symtab/Symbols.scala @@ -85,10 +85,9 @@ import Flags._; new TypeSymbol(this, pos, name).setFlag(DEFERRED); final def newTypeParameter(pos: int, name: Name) = newAbstractType(pos, name).setFlag(PARAM); - final def newSkolem(tparam: Symbol) = - new TypeSkolem(this, tparam.pos, tparam.name, tparam) - .setFlag(tparam.flags) - .setInfo(tparam.rawInfo); + final def newSkolem: Symbol = + new TypeSkolem(owner, pos, name, this) + .setFlag(flags); final def newClass(pos: int, name: Name) = new ClassSymbol(this, pos, name); final def newModuleClass(pos: int, name: Name) = @@ -134,7 +133,8 @@ import Flags._; final def isTrait = isClass & hasFlag(TRAIT); final def isAliasType = isType && !isClass && !hasFlag(DEFERRED); final def isAbstractType = isType && !isClass && hasFlag(DEFERRED); - final def isTypeParameter = isType && hasFlag(PARAM); + final def isTypeParameterOrSkolem = isType && hasFlag(PARAM); + final def isTypeParameter = isTypeParameterOrSkolem && deSkolemize == this; 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 @@ -265,32 +265,32 @@ import Flags._; final def info: Type = { var cnt = 0; while (validForRun != currentRun) { - //if (settings.debug.value) System.out.println("completing " + this);//DEBUG + //if (settings.debug.value) System.out.println("completing " + this);//DEBUG var ifs = infos; assert(ifs != null, this.name); while (ifs.prev != null) { ifs = ifs.prev; } - val tp = ifs.info; - //if (settings.debug.value) System.out.println("completing " + this.rawname + tp.getClass());//debug + val tp = ifs.info; + //if (settings.debug.value) System.out.println("completing " + this.rawname + tp.getClass());//debug if ((rawflags & LOCKED) != 0) { setInfo(ErrorType); throw CyclicReference(this, tp); } rawflags = rawflags | LOCKED; - val current = phase; + val current = phase; try { - phase = phaseWithId(ifs.start); + phase = phaseWithId(ifs.start); tp.complete(this); - // if (settings.debug.value && (validForRun == currentRun) System.out.println("completed " + this/* + ":" + info*/);//DEBUG + // if (settings.debug.value && (validForRun == currentRun) System.out.println("completed " + this/* + ":" + info*/);//DEBUG rawflags = rawflags & ~LOCKED } finally { - phase = current + phase = current } - cnt = cnt + 1; - // allow for two completions: - // one: sourceCompleter to LazyType, two: LazyType to completed type - if (cnt == 3) throw new Error("no progress in completing " + this + ":" + tp); + cnt = cnt + 1; + // allow for two completions: + // one: sourceCompleter to LazyType, two: LazyType to completed type + if (cnt == 3) throw new Error("no progress in completing " + this + ":" + tp); } rawInfo } @@ -397,14 +397,14 @@ import Flags._; */ final def isLess(that: Symbol): boolean = { def closureLength(sym: Symbol) = - if (sym.isAbstractType) 1 + sym.info.bounds.hi.closure.length - else sym.info.closure.length; + if (sym.isAbstractType) 1 + sym.info.bounds.hi.closure.length + else sym.info.closure.length; if (this.isType) - that.isType && - {val diff = closureLength(this) - closureLength(that); - diff > 0 || diff == 0 && this.id < that.id} + that.isType && + {val diff = closureLength(this) - closureLength(that); + diff > 0 || diff == 0 && this.id < that.id} else - that.isType || this.id < that.id; + that.isType || this.id < that.id; } /** A partial ordering between symbols. @@ -432,12 +432,12 @@ import Flags._; def filter(cond: Symbol => boolean): Symbol = if (hasFlag(OVERLOADED)) { //assert(info.isInstanceOf[OverloadedType], "" + this + ":" + info);//DEBUG - val alts = alternatives; - val alts1 = alts filter cond; - if (alts1 eq alts) this - else if (alts1.isEmpty) NoSymbol - else if (alts1.tail.isEmpty) alts1.head - else owner.newOverloaded(info.prefix, alts1) + val alts = alternatives; + val alts1 = alts filter cond; + if (alts1 eq alts) this + else if (alts1.isEmpty) NoSymbol + else if (alts1.tail.isEmpty) alts1.head + else owner.newOverloaded(info.prefix, alts1) } else if (cond(this)) this else NoSymbol; @@ -524,7 +524,7 @@ import Flags._; */ final def linkedModule: Symbol = if (owner.isPackageClass) - owner.info.decl(name.toTermName).suchThat( + owner.info.decl(name.toTermName).suchThat( sym => (sym hasFlag MODULE) && (sym.rawInfo ne NoType)); else NoSymbol; @@ -541,10 +541,10 @@ import Flags._; final def toInterface: Symbol = if (isImplClass) { - assert(!tpe.parents.isEmpty, this); - val iface = tpe.parents.last.symbol; - assert(nme.implClassName(iface.name) == name, this); - iface + assert(!tpe.parents.isEmpty, this); + val iface = tpe.parents.last.symbol; + assert(nme.implClassName(iface.name) == name, this); + iface } else this; /** The module corresponding to this module class (note that this @@ -575,8 +575,8 @@ import Flags._; var sym: Symbol = NoSymbol; while (!bcs.isEmpty && sym == NoSymbol) { if (!bcs.head.isImplClass) - sym = overriddenSymbol(bcs.head).suchThat(sym => !sym.hasFlag(DEFERRED)); - bcs = bcs.tail + sym = overriddenSymbol(bcs.head).suchThat(sym => !sym.hasFlag(DEFERRED)); + bcs = bcs.tail } sym } @@ -599,7 +599,7 @@ import Flags._; if (isTerm && (this hasFlag PRIVATE)) { setFlag(notPRIVATE); if (!hasFlag(DEFERRED)) setFlag(lateFINAL); - expandName(base) + expandName(base) } /** change name by appending $$ @@ -711,28 +711,28 @@ import Flags._; "" } if (isClass) - typeParamsString + " extends " + tp.resultType + typeParamsString + " extends " + tp.resultType else if (isAliasType) - typeParamsString + " = " + tp.resultType + typeParamsString + " = " + tp.resultType else if (isAbstractType) - tp match { - case TypeBounds(lo, hi) => - (if (lo.symbol == AllClass) "" else " >: " + lo) + - (if (hi.symbol == AnyClass) "" else " <: " + hi) - case _ => - "<: " + tp; - } + tp match { + case TypeBounds(lo, hi) => + (if (lo.symbol == AllClass) "" else " >: " + lo) + + (if (hi.symbol == AnyClass) "" else " <: " + hi) + case _ => + "<: " + tp; + } else if (isModule) - moduleClass.infoString(tp) + moduleClass.infoString(tp) else - tp match { - case PolyType(tparams, res) => - typeParamsString + infoString(res) - case MethodType(pts, res) => - pts.mkString("(", ",", ")") + infoString(res) - case _ => - ": " + tp - } + tp match { + case PolyType(tparams, res) => + typeParamsString + infoString(res) + case MethodType(pts, res) => + pts.mkString("(", ",", ")") + infoString(res) + case _ => + ": " + tp + } } def infosString = infos.toString(); @@ -799,11 +799,11 @@ import Flags._; override def name: Name = if (phase.flatClasses && !hasFlag(METHOD) && rawowner != NoSymbol && !rawowner.isPackageClass) { - if (flatname == nme.EMPTY) { - assert(rawowner.isClass); - flatname = newTermName(rawowner.name.toString() + "$" + rawname); - } - flatname + if (flatname == nme.EMPTY) { + assert(rawowner.isClass); + flatname = newTermName(rawowner.name.toString() + "$" + rawname); + } + flatname } else rawname; override def cloneSymbolImpl(owner: Symbol): Symbol = { @@ -826,11 +826,11 @@ import Flags._; if (tpeCache eq NoType) throw CyclicReference(this, typeConstructor); if (tpePhase != phase) { if (isValid(tpePhase)) { - tpePhase = phase + tpePhase = phase } else { if (isInitialized) tpePhase = phase; tpeCache = NoType; - val targs = if (phase.erasedTypes && this != ArrayClass) List() + val targs = if (phase.erasedTypes && this != ArrayClass) List() else unsafeTypeParams map (.tpe); tpeCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, this, targs) } @@ -838,32 +838,37 @@ import Flags._; assert(tpeCache != null/*, "" + this + " " + phase*/);//debug tpeCache } + override def typeConstructor: Type = { if (tyconCache == null || tyconRun != currentRun) { - tyconCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, this, List()); + tyconCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, this, List()); tyconRun = currentRun; } assert(tyconCache != null); tyconCache } + override def setInfo(tp: Type): this.type = { tpePhase = null; tyconCache = null; tp match { //debug - case TypeRef(_, sym, _) => - assert(sym != this, this); - case _ => + case TypeRef(_, sym, _) => + assert(sym != this, this); + case _ => } super.setInfo(tp); this } + override def reset(completer: Type): unit = { super.reset(completer); tpePhase = null; tyconCache = null; } + def cloneSymbolImpl(owner: Symbol): Symbol = new TypeSymbol(owner, pos, name); + if (util.Statistics.enabled) typeSymbolCount = typeSymbolCount + 1; } @@ -894,11 +899,11 @@ import Flags._; override def name: Name = if (phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass) { - if (flatname == nme.EMPTY) { - assert(rawowner.isClass); - flatname = newTypeName(rawowner.name.toString() + "$" + rawname); - } - flatname + if (flatname == nme.EMPTY) { + assert(rawowner.isClass); + flatname = newTypeName(rawowner.name.toString() + "$" + rawname); + } + flatname } else rawname; private var thisTypeCache: Type = _; @@ -911,10 +916,10 @@ import Flags._; thisTypePhase = phase; if (!(isValid(p) /*|| thisTypePhase != null && thisTypePhase.erasedTypes && phase.erasedTypes*/)) { - thisTypeCache = - if (isModuleClass && !isRoot && !phase.erasedTypes) - singleType(owner.thisType, sourceModule); - else ThisType(this); + thisTypeCache = + if (isModuleClass && !isRoot && !phase.erasedTypes) + singleType(owner.thisType, sourceModule); + else ThisType(this); } } thisTypeCache @@ -978,6 +983,16 @@ import Flags._; syms1 } + def newSkolems(tparams: List[Symbol]): List[Symbol] = { + val tskolems = tparams map (.newSkolem); + val ltp = new LazyType { + override def complete(sym: Symbol): unit = + sym setInfo sym.deSkolemize.info.substSym(tparams, tskolems); + } + tskolems foreach (.setInfo(ltp)); + tskolems + } + /** An exception for cyclic references of symbol definitions */ case class CyclicReference(sym: Symbol, info: Type) extends TypeError("illegal cyclic reference involving " + sym); diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala index eba1ef7161..0748802f29 100755 --- a/sources/scala/tools/nsc/symtab/Types.scala +++ b/sources/scala/tools/nsc/symtab/Types.scala @@ -51,6 +51,7 @@ import Flags._; /** The base class for all types */ trait Type { + /** Types for which asSeenFrom always is the identity, no matter what prefix or owner */ def isTrivial: boolean = false; /** The symbol associated with the type */ @@ -1359,6 +1360,10 @@ import Flags._; mapOver( if (tparam == sym || tparam.owner.isTerm && !(tparams contains tparam)) tp else rawTypeRef(pre, tparam, args)) +/* not yet (GADT) + case SingleType(pre, sym) if (sym.isThisSym) => + pre +*/ case PolyType(tparams1, restpe) => assert(tparams.isEmpty); new DeSkolemizeMap(tparams1).mapOver(tp) @@ -1371,6 +1376,29 @@ import Flags._; } val deSkolemize = new DeSkolemizeMap(List()); + object freeTypeParams extends TypeTraverser { + private var result: List[Symbol] = _; + private def includeIfAbstract(sym: Symbol): unit = { + if (sym.isAbstractType && !result.contains(sym)) result = sym :: result; + } + override def traverse(tp: Type): TypeTraverser = { + tp match { + case TypeRef(NoPrefix, sym, _) => + includeIfAbstract(sym) + case TypeRef(ThisType(_), sym, _) => + includeIfAbstract(sym) + case _ => + } + mapOver(tp); + this + } + def collect(tp: Type): List[Symbol] = { + result = List(); + traverse(tp); + result + } + } + // Helper Methods ------------------------------------------------------------- final def isValid(p: Phase): boolean = diff --git a/sources/scala/tools/nsc/transform/Mixin.scala b/sources/scala/tools/nsc/transform/Mixin.scala index 46b2796fad..77c32aeab5 100755 --- a/sources/scala/tools/nsc/transform/Mixin.scala +++ b/sources/scala/tools/nsc/transform/Mixin.scala @@ -106,6 +106,7 @@ abstract class Mixin extends InfoTransform { val member1 = addMember( clazz, member.cloneSymbol(clazz) + setPos clazz.pos setFlag MIXEDIN resetFlag (DEFERRED | lateDEFERRED)); member1.asInstanceOf[TermSymbol] setAlias member; } @@ -119,7 +120,9 @@ abstract class Mixin extends InfoTransform { if (member hasFlag ACCESSOR) { val member1 = addMember( clazz, - member.cloneSymbol(clazz) setFlag (MIXEDIN | FINAL) resetFlag (DEFERRED | lateDEFERRED)); + member.cloneSymbol(clazz) + setPos clazz.pos + setFlag (MIXEDIN | FINAL) resetFlag (DEFERRED | lateDEFERRED)); if (!member.isSetter) member.tpe match { case MethodType(List(), ConstantType(_)) => @@ -131,12 +134,14 @@ abstract class Mixin extends InfoTransform { setInfo member.tpe.resultType) } } else if (member hasFlag SUPERACCESSOR) { - val member1 = addMember(clazz, member.cloneSymbol(clazz)) setFlag MIXEDIN; + val member1 = addMember(clazz, member.cloneSymbol(clazz)) + setPos clazz.pos setFlag MIXEDIN; assert(member1.alias != NoSymbol, member1); val alias1 = rebindSuper(clazz, member.alias, mixin); member1.asInstanceOf[TermSymbol] setAlias alias1; } else if (member.isMethod && member.isModule && !(member hasFlag (LIFTED | BRIDGE))) { - addMember(clazz, member.cloneSymbol(clazz) setFlag MIXEDIN resetFlag (DEFERRED | lateDEFERRED)) + addMember(clazz, member.cloneSymbol(clazz)) resetFlag (DEFERRED | lateDEFERRED) + setPos clazz.pos setFlag MIXEDIN } } } diff --git a/sources/scala/tools/nsc/typechecker/Contexts.scala b/sources/scala/tools/nsc/typechecker/Contexts.scala index 4af9f95202..da911ceb78 100755 --- a/sources/scala/tools/nsc/typechecker/Contexts.scala +++ b/sources/scala/tools/nsc/typechecker/Contexts.scala @@ -82,14 +82,17 @@ import scala.tools.nsc.util.Position; c.tree = tree; c.owner = owner; c.scope = scope; - c.enclClass = tree match { - case Template(_, _) | PackageDef(_, _) => c - case _ => this.enclClass + tree match { + case Template(_, _) | PackageDef(_, _) => + c.enclClass = c; + c.thisSkolemType = skolemizedThisType(c.owner) + case _ => + c.enclClass = this.enclClass; + c.thisSkolemType = this.thisSkolemType } c.variance = this.variance; c.depth = if (scope == this.scope) this.depth else this.depth + 1; c.imports = imports; - c.thisSkolemType = if (owner.isClass) owner.thisType else thisSkolemType; c.reportAmbiguousErrors = this.reportAmbiguousErrors; c.reportGeneralErrors = this.reportGeneralErrors; c.checking = this.checking; @@ -126,6 +129,19 @@ import scala.tools.nsc.util.Position; c } + def skolemizedThisType(clazz: Symbol): Type = { + clazz.thisType + /* not yet (GADT) + val tparams = clazz.unsafeTypeParams; + if (tparams.isEmpty) clazz.thisType + else { + val self = clazz.newThisSym(clazz.pos) + setInfo clazz.typeOfThis.substSym(tparams, newSkolems(tparams)); + singleType(clazz.thisType, self) + } + */ + } + def error(pos: int, msg: String): unit = if (reportGeneralErrors) unit.error(pos, if (checking) "**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg) diff --git a/sources/scala/tools/nsc/typechecker/Infer.scala b/sources/scala/tools/nsc/typechecker/Infer.scala index 903e42b976..e6568b20b5 100755 --- a/sources/scala/tools/nsc/typechecker/Infer.scala +++ b/sources/scala/tools/nsc/typechecker/Infer.scala @@ -77,29 +77,6 @@ package scala.tools.nsc.typechecker; List.map2(bounds, targs)((bound, targ) => bound containsType targ) forall (x => x) } - object freeTypeParams extends TypeTraverser { - private var result: List[Symbol] = _; - private def includeIfAbstract(sym: Symbol): unit = { - if (sym.isAbstractType && !result.contains(sym)) result = sym :: result; - } - override def traverse(tp: Type): TypeTraverser = { - tp match { - case TypeRef(NoPrefix, sym, _) => - includeIfAbstract(sym) - case TypeRef(ThisType(_), sym, _) => - includeIfAbstract(sym) - case _ => - } - mapOver(tp); - this - } - def collect(tp: Type): List[Symbol] = { - result = List(); - traverse(tp); - result - } - } - /** Solve constraint collected in types `tvars' * @param tvars All type variables to be instantiated. * @param tparams The type parameters corresponding to `tvars' @@ -240,7 +217,7 @@ package scala.tools.nsc.typechecker; if (sym.isError) { tree setSymbol sym setType ErrorType } else if (sym.owner.hasFlag(INCONSTRUCTOR) && - !sym.isTypeParameter && !sym.isConstructor && + !sym.isTypeParameterOrSkolem && !sym.isConstructor && (site.isInstanceOf[This] || site.isInstanceOf[Super]) && !phase.erasedTypes) { errorTree(tree, "" + sym + " cannot be accessed from constructor"); } else { diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala index 639b2215cf..3f7dd81be5 100755 --- a/sources/scala/tools/nsc/typechecker/Namers.scala +++ b/sources/scala/tools/nsc/typechecker/Namers.scala @@ -126,7 +126,8 @@ trait Namers: Analyzer { def finish = finishWith(List()); def skolemize(tparams: List[AbsTypeDef]): unit = { - for (val tp <- tparams) tp.symbol = tp.symbol.owner.newSkolem(tp.symbol) + val tskolems = newSkolems(tparams map (.symbol)); + for (val Pair(tparam, tskolem) <- tparams zip tskolems) tparam.symbol = tskolem } if (tree.symbol == NoSymbol) { @@ -388,6 +389,7 @@ trait Namers: Analyzer { new Namer(context.makeNewScope(tree, sym)).aliasTypeSig(sym, tparams, rhs) case AbsTypeDef(_, _, lo, hi) => + //System.out.println("bounds of " + sym + ":" + sym.tpe + " = " + typer.typedType(hi).tpe); TypeBounds(typer.typedType(lo).tpe, typer.typedType(hi).tpe); case Import(expr, selectors) => @@ -444,7 +446,7 @@ trait Namers: Analyzer { sym.isValueParameter && sym.owner.isClass && sym.owner.hasFlag(CASE)) context.error(sym.pos, "pass-by-name arguments not allowed for case class parameters"); if ((sym.flags & DEFERRED) != 0) { - if (!sym.isValueParameter && !sym.isTypeParameter && + if (!sym.isValueParameter && !sym.isTypeParameterOrSkolem && (!sym.owner.isClass || sym.owner.isModuleClass || sym.owner.isAnonymousClass)) { context.error(sym.pos, "only classes can have declared but undefined members" + diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala index 72cfaf733e..5ca4feb0b5 100755 --- a/sources/scala/tools/nsc/typechecker/Typers.scala +++ b/sources/scala/tools/nsc/typechecker/Typers.scala @@ -2,6 +2,7 @@ * Copyright 2005 LAMP/EPFL * @author Martin Odersky */ +// $Id$ //todo: rewrite or disallow new T where T is a trait (currently: not a member of T) package scala.tools.nsc.typechecker; @@ -197,7 +198,8 @@ import collection.mutable.HashMap; if (o == sym.owner) badSymbol = sym } else if (sym.owner.isTerm) { val e = scope.lookupEntry(sym.name); - if (e != null && e.sym == sym && e.owner == scope && !e.sym.isTypeParameter) badSymbol = e.sym + if (e != null && e.sym == sym && e.owner == scope && !e.sym.isTypeParameterOrSkolem) + badSymbol = e.sym } } if (badSymbol == NoSymbol) @@ -388,6 +390,7 @@ import collection.mutable.HashMap; } if (context.reportGeneralErrors && !tree.tpe.isError && !pt.isError) { // (13); the condition prevents chains of views + if (settings.debug.value) log("inferring view from " + tree.tpe + " to " + pt); val coercion = inferView(tree.pos, tree.tpe, pt, true); if (coercion != EmptyTree) { if (settings.debug.value) log("inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe); @@ -960,7 +963,6 @@ import collection.mutable.HashMap; defEntry = cx.scope.lookupEntry(name); if (defEntry != null) { defSym = defEntry.sym; - assert(pre eq cx.enclClass.owner.thisType, "mismatch " + pre + " " + cx.enclClass.owner + " " + defSym);//debug } else { cx = cx.enclClass; defSym = pre.member(name) filter (sym => context.isAccessible(sym, pre, false)); @@ -990,7 +992,7 @@ import collection.mutable.HashMap; ambiguousError( "it is both defined in " + defSym.owner + " and imported subsequently by \n" + imports.head); - else if (!defSym.owner.isClass || defSym.owner.isPackageClass || defSym.isTypeParameter) + else if (!defSym.owner.isClass || defSym.owner.isPackageClass || defSym.isTypeParameterOrSkolem) pre = NoPrefix else qual = atPos(tree.pos)(gen.mkQualifier(pre)); -- cgit v1.2.3