diff options
author | Lukas Rytz <lukas.rytz@epfl.ch> | 2009-04-28 13:33:47 +0000 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@epfl.ch> | 2009-04-28 13:33:47 +0000 |
commit | bdc8c11581b0fc67cf895ba349e43b2081e29c59 (patch) | |
tree | c7964a41b187a464ae02e1b1debc0b79326fa26c /src/compiler | |
parent | 03429aee94c9eb4b1d2a4aa7fd8fadfea6e17bf1 (diff) | |
download | scala-bdc8c11581b0fc67cf895ba349e43b2081e29c59.tar.gz scala-bdc8c11581b0fc67cf895ba349e43b2081e29c59.tar.bz2 scala-bdc8c11581b0fc67cf895ba349e43b2081e29c59.zip |
removed Namers.scala.1 / .2
Diffstat (limited to 'src/compiler')
-rwxr-xr-x | src/compiler/scala/tools/nsc/typechecker/Namers.scala.1 | 1047 | ||||
-rwxr-xr-x | src/compiler/scala/tools/nsc/typechecker/Namers.scala.2 | 1046 |
2 files changed, 0 insertions, 2093 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala.1 b/src/compiler/scala/tools/nsc/typechecker/Namers.scala.1 deleted file mode 100755 index 910418ba65..0000000000 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala.1 +++ /dev/null @@ -1,1047 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2009 LAMP/EPFL - * @author Martin Odersky - */ -// $Id: Namers.scala 17117 2009-02-16 14:56:54Z odersky $ - -package scala.tools.nsc.typechecker - -import scala.collection.mutable.HashMap -import scala.tools.nsc.util.Position -import symtab.Flags -import symtab.Flags._ - -/** This trait declares methods to create symbols and to enter them into scopes. - * - * @author Martin Odersky - * @version 1.0 - */ -trait Namers { self: Analyzer => - import global._ - import definitions._ - import posAssigner.atPos - - /** Convert to corresponding type parameters all skolems of method parameters - * which appear in `tparams`. - */ - class DeSkolemizeMap(tparams: List[Symbol]) extends TypeMap { - def apply(tp: Type): Type = tp match { - case TypeRef(pre, sym, args) - if (sym.isTypeSkolem && (tparams contains sym.deSkolemize)) => -// println("DESKOLEMIZING "+sym+" in "+sym.owner) - mapOver(rawTypeRef(NoPrefix, sym.deSkolemize, args)) -/* - case PolyType(tparams1, restpe) => - new DeSkolemizeMap(tparams1 ::: tparams).mapOver(tp) - case ClassInfoType(parents, decls, clazz) => - val parents1 = List.mapConserve(parents)(this) - if (parents1 eq parents) tp else ClassInfoType(parents1, decls, clazz) -*/ - case _ => - mapOver(tp) - } - } - - private class NormalNamer(context : Context) extends Namer(context) - def newNamer(context : Context) : Namer = new NormalNamer(context) - - private[typechecker] val caseClassOfModuleClass = new HashMap[Symbol, ClassDef] - - def resetNamer() { - caseClassOfModuleClass.clear - } - - abstract class Namer(val context: Context) { - - val typer = newTyper(context) - - def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym = { - if (!mods.privateWithin.isEmpty) - sym.privateWithin = typer.qualifyingClassContext(tree, mods.privateWithin, true).owner - sym - } - - def inConstructorFlag: Long = - if (context.owner.isConstructor && !context.inConstructorSuffix || context.owner.isEarly) INCONSTRUCTOR - else 0l - - def moduleClassFlags(moduleFlags: Long) = - (moduleFlags & ModuleToClassFlags) | FINAL | inConstructorFlag - - def updatePosFlags(sym: Symbol, pos: Position, flags: Long): Symbol = { - if (settings.debug.value) log("overwriting " + sym) - val lockedFlag = sym.flags & LOCKED - sym.reset(NoType) - sym setPos pos - sym.flags = flags | lockedFlag - if (sym.isModule && sym.moduleClass != NoSymbol) - updatePosFlags(sym.moduleClass, pos, moduleClassFlags(flags)) - if (sym.owner.isPackageClass && - (sym.linkedSym.rawInfo.isInstanceOf[loaders.SymbolLoader] || - sym.linkedSym.rawInfo.isComplete && runId(sym.validTo) != currentRunId)) - // pre-set linked symbol to NoType, in case it is not loaded together with this symbol. - sym.linkedSym.setInfo(NoType) - sym - } - - private def isTemplateContext(context: Context): Boolean = context.tree match { - case Template(_, _, _) => true - case Import(_, _) => isTemplateContext(context.outer) - case _ => false - } - - private var innerNamerCache: Namer = null - protected def makeConstructorScope(classContext : Context) : Context = { - val outerContext = classContext.outer.outer - outerContext.makeNewScope(outerContext.tree, outerContext.owner)(Constructor1ScopeKind) - } - - def namerOf(sym: Symbol): Namer = { - - def innerNamer: Namer = { - if (innerNamerCache eq null) - innerNamerCache = - if (!isTemplateContext(context)) this - else newNamer(context.make(context.tree, context.owner, scopeFor(context.tree, InnerScopeKind))) - innerNamerCache - } - - def primaryConstructorParamNamer: Namer = { //todo: can we merge this with SCCmode? - val classContext = context.enclClass - val paramContext = makeConstructorScope(classContext) - val unsafeTypeParams = context.owner.unsafeTypeParams - unsafeTypeParams foreach(sym => paramContext.scope.enter(sym)) - newNamer(paramContext) - } - if (sym.isTerm) { - if (sym.hasFlag(PARAM) && sym.owner.isPrimaryConstructor) - primaryConstructorParamNamer - else if (sym.hasFlag(PARAMACCESSOR) && !inIDE) - primaryConstructorParamNamer - else innerNamer - } else innerNamer - } - - protected def conflict(newS : Symbol, oldS : Symbol) : Boolean = { - (!oldS.isSourceMethod || - nme.isSetterName(newS.name) || - newS.owner.isPackageClass) && - !((newS.owner.isTypeParameter || newS.owner.isAbstractType) && - newS.name.length==1 && newS.name(0)=='_') //@M: allow repeated use of `_' for higher-order type params - } - - // IDE hook - protected def setInfo[Sym <: Symbol](sym : Sym)(tpe : LazyType) : Sym = sym.setInfo(tpe) - - private def doubleDefError(pos: Position, sym: Symbol) { - context.error(pos, - sym.name.toString() + " is already defined as " + - (if (sym.hasFlag(SYNTHETIC)) - "(compiler-generated) "+ (if (sym.isModule) "case class companion " else "") - else "") + - (if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString())) - } - - private def inCurrentScope(m: Symbol): Boolean = { - if (context.owner.isClass) context.owner == m.owner - else m.owner.isClass && context.scope == m.owner.info.decls - } - - def enterInScope(sym: Symbol): Symbol = enterInScope(sym, context.scope) - - def enterInScope(sym: Symbol, scope: Scope): Symbol = { - // allow for overloaded methods - if (!(sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass)) { - var prev = scope.lookupEntryWithContext(sym.name)(context.owner); - if ((prev ne null) && inIDE) { - var guess = prev - while ((guess ne null) && (guess.sym ne sym)) guess = scope.lookupNextEntry(guess) - if (guess != null) prev = guess - while (prev != null && (!prev.sym.hasRawInfo || !prev.sym.rawInfo.isComplete || - (prev.sym.sourceFile == null && sym.getClass == prev.sym.getClass))) { - if (!prev.sym.hasRawInfo || prev.sym.rawInfo.isComplete) { - Console.println("DITCHING: " + prev.sym) - } - scope unlink prev.sym - prev = scope.lookupNextEntry(prev) - } - val sym0 = scope enter sym - if (sym0 ne sym) { - Console.println("WEIRD: " + sym0 + " vs. " + sym + " " + sym0.id + " " + sym.id + " " + sym.sourceFile + " " + sym0.sourceFile) - } - if (prev != null && (sym0 ne prev.sym) && conflict(sym0,prev.sym)) { - doubleDefError(sym0.pos, prev.sym) - } - sym0 - } else if ((prev ne null) && prev.owner == scope && conflict(sym, prev.sym)) { - doubleDefError(sym.pos, prev.sym) - sym setInfo ErrorType // don't do this in IDE for stability - scope unlink prev.sym // let them co-exist... - scope enter sym - } else scope enter sym - } else scope enter sym - } - - def enterPackageSymbol(pos: Position, name: Name): Symbol = { - val (cscope, cowner) = - if (context.owner == EmptyPackageClass) (RootClass.info.decls, RootClass) - else (context.scope, context.owner) - val p: Symbol = cscope.lookupWithContext(name)(context.owner) - if (p.isPackage && cscope == p.owner.info.decls) { - p - } else { - val pkg = cowner.newPackage(pos, name) - // IDE: newScope should be ok because packages are never destroyed. - if (inIDE) assert(!pkg.moduleClass.hasRawInfo || !pkg.moduleClass.rawInfo.isComplete) - pkg.moduleClass.setInfo(new PackageClassInfoType(newScope, pkg.moduleClass, null)) - pkg.setInfo(pkg.moduleClass.tpe) - enterInScope(pkg, cscope) - } - } - - def enterClassSymbol(tree : ClassDef): Symbol = { - var c: Symbol = context.scope.lookupWithContext(tree.name)(context.owner); - if (!inIDE && c.isType && c.owner.isPackageClass && context.scope == c.owner.info.decls && !currentRun.compiles(c)) { - updatePosFlags(c, tree.pos, tree.mods.flags) - setPrivateWithin(tree, c, tree.mods) - } else { - var sym = context.owner.newClass(tree.pos, tree.name) - sym = sym.setFlag(tree.mods.flags | inConstructorFlag) - sym = setPrivateWithin(tree, sym, tree.mods) - c = enterInScope(sym) - } - if (c.owner.isPackageClass) { - val file = context.unit.source.file - val clazz = c.asInstanceOf[ClassSymbol] - if (settings.debug.value && (clazz.sourceFile ne null) && !clazz.sourceFile.equals(file)) { - Console.err.println("SOURCE MISMATCH: " + clazz.sourceFile + " vs. " + file + " SYM=" + c); - } - clazz.sourceFile = file - if (clazz.sourceFile ne null) { - assert(inIDE || !currentRun.compiles(clazz) || clazz.sourceFile == currentRun.symSource(c)); - currentRun.symSource(c) = clazz.sourceFile - } - } - assert(c.name.toString.indexOf('(') == -1) - c - } - - /** Enter a module symbol. The tree parameter can be either a module definition - * or a class definition */ - def enterModuleSymbol(tree : ModuleDef): Symbol = { - // .pos, mods.flags | MODULE | FINAL, name - var m: Symbol = context.scope.lookupWithContext(tree.name)(context.owner) - val moduleFlags = tree.mods.flags | MODULE | FINAL - if (m.isModule && !m.isPackage && inCurrentScope(m) && - ((!inIDE && !currentRun.compiles(m)) || (m hasFlag SYNTHETIC))) { - updatePosFlags(m, tree.pos, moduleFlags) - setPrivateWithin(tree, m, tree.mods) - context.unit.synthetics -= m - } else { - m = context.owner.newModule(tree.pos, tree.name) - m.setFlag(moduleFlags) - m = setPrivateWithin(tree, m, tree.mods) - m = enterInScope(m) - - m.moduleClass.setFlag(moduleClassFlags(moduleFlags)) - setPrivateWithin(tree, m.moduleClass, tree.mods) - } - if (m.owner.isPackageClass) { - m.moduleClass.sourceFile = context.unit.source.file - currentRun.symSource(m) = m.moduleClass.sourceFile - } - m - } - - def enterSyms(trees: List[Tree]): Namer = { - var namer : Namer = this - for (tree <- trees) { - val txt = namer.enterSym(tree) - if (!(txt eq namer.context)) namer = newNamer(txt) - } - namer - } - - def newTypeSkolems(tparams: List[Symbol]): List[Symbol] = { - val tskolems = tparams map (_.newTypeSkolem) - val ltp = new LazyType { - override def complete(sym: Symbol) { - sym setInfo sym.deSkolemize.info.substSym(tparams, tskolems) //@M the info of a skolem is the skolemized info of the actual type parameter of the skolem - } - } - tskolems foreach (_.setInfo(ltp)) - tskolems - } - - /** Replace type parameters with their TypeSkolems, which can later be deskolemized to the original type param - * (a skolem is a representation of a bound variable when viewed inside its scope) - */ - def skolemize(tparams: List[TypeDef]) { - val tskolems = newTypeSkolems(tparams map (_.symbol)) - for ((tparam, tskolem) <- tparams zip tskolems) tparam.symbol = tskolem - } - - def applicableTypeParams(owner: Symbol): List[Symbol] = - if (inIDE && (owner eq NoSymbol)) List() - else if (owner.isTerm || owner.isPackageClass) List() - else applicableTypeParams(owner.owner) ::: owner.typeParams - - def enterSym(tree: Tree): Context = try { - - def finishWith(tparams: List[TypeDef]) { - val sym = tree.symbol - if (settings.debug.value) log("entered " + sym + " in " + context.owner + ", scope-id = " + context.scope.hashCode()); - var ltype = namerOf(sym).typeCompleter(tree) - if (!tparams.isEmpty) { - //@M! TypeDef's type params are handled differently - //@M e.g., in [A[x <: B], B], A and B are entered first as both are in scope in the definition of x - //@M x is only in scope in `A[x <: B]' - if(!sym.isAbstractType) //@M TODO: change to isTypeMember ? - newNamer(context.makeNewScope(tree, sym)(FinishWithScopeKind)).enterSyms(tparams) - ltype = new PolyTypeCompleter(tparams, ltype, tree, sym, context) //@M - if (sym.isTerm) skolemize(tparams) - } - setInfo(sym)(ltype) - } - def finish = finishWith(List()) - - if (tree.symbol == NoSymbol) { - val owner = context.owner - tree match { - case PackageDef(name, stats) => - tree.symbol = enterPackageSymbol(tree.pos, name) - val namer = newNamer( - context.make(tree, tree.symbol.moduleClass, tree.symbol.info.decls)) - namer.enterSyms(stats) - case tree @ ClassDef(mods, name, tparams, impl) => - tree.symbol = enterClassSymbol(tree) - finishWith(tparams) - if ((mods.flags & CASE) != 0) { - var m: Symbol = context.scope.lookupWithContext(tree.name.toTermName)(context.owner).filter(! _.isSourceMethod) - if (!(m.isModule && inCurrentScope(m) && (inIDE || currentRun.compiles(m)))) { - m = enterSyntheticSym(caseModuleDef(tree)) - } - caseClassOfModuleClass(m.moduleClass) = tree - } - case tree @ ModuleDef(mods, name, _) => - tree.symbol = enterModuleSymbol(tree) - tree.symbol.moduleClass.setInfo(namerOf(tree.symbol).moduleClassTypeCompleter((tree))) - finish - - case ValDef(mods, name, tp, rhs) => - if ((!context.owner.isClass || - (mods.flags & (PRIVATE | LOCAL)) == (PRIVATE | LOCAL) || - name.endsWith(nme.OUTER, nme.OUTER.length) || - context.unit.isJava) && - (mods.flags & LAZY) == 0) { - tree.symbol = enterInScope(owner.newValue(tree.pos, name) - .setFlag(mods.flags)) - finish - } else { - // add getter and possibly also setter - val accflags: Long = ACCESSOR | - (if ((mods.flags & MUTABLE) != 0) mods.flags & ~MUTABLE & ~PRESUPER - else mods.flags & ~PRESUPER | STABLE) - if (nme.isSetterName(name)) - context.error(tree.pos, "Names of vals or vars may not end in `_='") - var getter = owner.newMethod(tree.pos, name).setFlag(accflags) - setPrivateWithin(tree, getter, mods) - getter = enterInScope(getter).asInstanceOf[TermSymbol] - setInfo(getter)(namerOf(getter).getterTypeCompleter(tree)) - if ((mods.flags & MUTABLE) != 0) { - var setter = owner.newMethod(tree.pos, nme.getterToSetter(name)) - .setFlag(accflags & ~STABLE & ~CASEACCESSOR) - setPrivateWithin(tree, setter, mods) - setter = enterInScope(setter).asInstanceOf[TermSymbol] - setInfo(setter)(namerOf(setter).setterTypeCompleter(tree)) - } - tree.symbol = - if ((mods.flags & DEFERRED) == 0) { - var vsym = - if (!context.owner.isClass) { - assert((mods.flags & LAZY) != 0) // if not a field, it has to be a lazy val - owner.newValue(tree.pos, name + "$lzy" ).setFlag(mods.flags | MUTABLE) - } else { - owner.newValue(tree.pos, nme.getterToLocal(name)) - .setFlag(mods.flags & FieldFlags | PRIVATE | LOCAL | (if ((mods.flags & LAZY) != 0) MUTABLE else 0)) - } - vsym = enterInScope(vsym).asInstanceOf[TermSymbol] - setInfo(vsym)(namerOf(vsym).typeCompleter(tree)) - if ((mods.flags & LAZY) != 0) - vsym.setLazyAccessor(getter) - vsym - } else getter - } - case DefDef(mods, nme.CONSTRUCTOR, tparams, _, _, _) => - var sym = owner.newConstructor(tree.pos).setFlag(mods.flags | owner.getFlag(ConstrFlags)) - setPrivateWithin(tree, sym, mods) - tree.symbol = enterInScope(sym) - finishWith(tparams) - case DefDef(mods, name, tparams, _, _, _) => - var sym = (owner.newMethod(tree.pos, name)).setFlag(mods.flags) - setPrivateWithin(tree, sym, mods) - tree.symbol = enterInScope(sym) - finishWith(tparams) - case TypeDef(mods, name, tparams, _) => - var flags: Long = mods.flags - if ((flags & PARAM) != 0) flags |= DEFERRED - var sym = new TypeSymbol(owner, tree.pos, name).setFlag(flags) - setPrivateWithin(tree, sym, mods) - tree.symbol = enterInScope(sym) - finishWith(tparams) - case DocDef(_, defn) => - enterSym(defn) - case imp @ Import(_, _) => - tree.symbol = NoSymbol.newImport(tree.pos) - setInfo(tree.symbol)(namerOf(tree.symbol).typeCompleter(tree)) - return (context.makeNewImport(imp)) - case _ => - } - } - this.context - } catch { - case ex: TypeError => - //Console.println("caught " + ex + " in enterSym")//DEBUG - typer.reportTypeError(tree.pos, ex) - this.context - } - - def enterSyntheticSym(tree: Tree): Symbol = { - enterSym(tree) - context.unit.synthetics(tree.symbol) = tree - tree.symbol - } - -// --- Lazy Type Assignment -------------------------------------------------- - - def typeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => - if (settings.debug.value) log("defining " + sym + Flags.flagsToString(sym.flags)+sym.locationString) - val tp = typeSig(tree) - tp match { - case TypeBounds(lo, hi) => - // check that lower bound is not an F-bound - for (val t <- lo) { - t match { - case TypeRef(_, sym, _) => sym.initialize - case _ => - } - } - case _ => - } - sym.setInfo(tp) - if ((sym.isAliasType || sym.isAbstractType) && !(sym hasFlag PARAM) && - !typer.checkNonCyclic(tree.pos, tp)) - sym.setInfo(ErrorType) // this early test is there to avoid infinite baseTypes when - // adding setters and getters --> bug798 - if (settings.debug.value) log("defined " + sym); - validate(sym) - } - - def moduleClassTypeCompleter(tree: Tree) = { - mkTypeCompleter(tree) { sym => - val moduleSymbol = tree.symbol - assert(moduleSymbol.moduleClass == sym) - if (inIDE && moduleSymbol.rawInfo.isComplete) { - // reset! - } - moduleSymbol.info // sets moduleClass info as a side effect. - //assert(sym.rawInfo.isComplete) - } - } - - def getterTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => - if (settings.debug.value) log("defining " + sym) - sym.setInfo(PolyType(List(), typeSig(tree))) - if (settings.debug.value) log("defined " + sym) - validate(sym) - } - - def setterTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => - if (settings.debug.value) log("defining " + sym); - sym.setInfo(MethodType(List(typeSig(tree)), UnitClass.tpe)) - if (settings.debug.value) log("defined " + sym); - validate(sym) - } - - def selfTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => - var selftpe = typer.typedType(tree).tpe - if (!(selftpe.typeSymbol isNonBottomSubClass sym.owner)) - selftpe = intersectionType(List(sym.owner.tpe, selftpe)) -// println("completing self of "+sym.owner+": "+selftpe) - sym.setInfo(selftpe) - } - - private def widenIfNotFinal(sym: Symbol, tpe: Type, pt: Type): Type = { - val getter = - if (sym.isValue && sym.owner.isClass && (sym hasFlag PRIVATE)) - sym.getter(sym.owner) - else sym - def isHidden(tp: Type): Boolean = tp match { - case SingleType(pre, sym) => - (sym isLessAccessibleThan getter) || isHidden(pre) - case ThisType(sym) => - sym isLessAccessibleThan getter - case p: SimpleTypeProxy => - isHidden(p.underlying) - case _ => - false - } - val tpe1 = tpe.deconst - val tpe2 = tpe1.widen - if ((sym.isVariable || sym.isMethod && !(sym hasFlag ACCESSOR))) - if (tpe2 <:< pt) tpe2 else tpe1 - else if (isHidden(tpe)) tpe2 - else if (!(sym hasFlag FINAL)) tpe1 - else tpe - } - - def enterValueParams(owner: Symbol, vparamss: List[List[ValDef]]): List[List[Symbol]] = { - def enterValueParam(param: ValDef): Symbol = { - if (inIDE) param.symbol = { - var sym = owner.newValueParameter(param.pos, param.name). - setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT)) - setPrivateWithin(param, sym, param.mods) - sym = enterInScope(sym).asInstanceOf[TermSymbol] - if (!sym.hasRawInfo || sym.rawInfo.isComplete) - setInfo(sym)(typeCompleter(param)) - sym - } else param.symbol = setInfo( - enterInScope{ - val sym = owner.newValueParameter(param.pos, param.name). - setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT)) - setPrivateWithin(param, sym, param.mods) - })(typeCompleter(param)) - param.symbol - } - vparamss.map(_.map(enterValueParam)) - } - - private def templateSig(templ: Template): Type = { - val clazz = context.owner - def checkParent(tpt: Tree): Type = { - val tp = tpt.tpe - if (tp.typeSymbol == context.owner) { - context.error(tpt.pos, ""+tp.typeSymbol+" inherits itself") - AnyRefClass.tpe - } else if (tp.isError) { - AnyRefClass.tpe - } else { - tp - } - } - def enterSelf(self: ValDef) { - if (!self.tpt.isEmpty) { - clazz.typeOfThis = selfTypeCompleter(self.tpt) - self.symbol = clazz.thisSym.setPos(self.pos) - } else { - self.tpt.tpe = NoType - if (self.name != nme.WILDCARD) { - clazz.typeOfThis = clazz.tpe - self.symbol = clazz.thisSym - } else if (self ne emptyValDef) { - self.symbol = clazz.newThisSym(self.pos) setInfo clazz.tpe - } - } - if (self.name != nme.WILDCARD) { - self.symbol.name = self.name - self.symbol = context.scope enter self.symbol - } - } - var templateNamer = newNamer(context.make(templ, clazz, decls)) - templateNamer = templateNamer.enterSyms(template.body filter treeInfo.isEarlyType) - var parents = typer.parentTypes(templ) map checkParent - enterSelf(templ.self) - val decls = newClassScope(clazz) - templateNamer = templateNamer.enterSyms(templ.body) - - /* add overridden virtuals to parents - val overridden = clazz.overriddenVirtuals - if (!overridden.isEmpty) - parents = parents ::: ( overridden map ( - sym => TypeRef(clazz.owner.thisType, sym, clazz.typeParams map (_.tpe)))) - println("Parents of "+clazz+":"+parents) - - // check that virtual classses are only defined as members of templates - if (clazz.isVirtualClass && !clazz.owner.isClass) - context.error( - clazz.pos, - "virtual traits and their subclasses must be defined as members of some other class") - - // make subclasses of virtual classes virtual as well; check that - // they are defined in same scope. - val virtualParents = parents map (_.typeSymbol) filter (_.isVirtualClass) - virtualParents find { - vp => !(clazz.owner.isClass && (clazz.owner isSubClass vp.owner)) - } match { - case Some(vp) => - context.error( - clazz.pos, - "subclass of virtual "+vp+ - " needs to be defined at same level,\nas member of "+vp.owner) - case None => - if (!virtualParents.isEmpty) clazz setFlag DEFERRED // make it virtual - } - */ - - // add apply and unapply methods to companion objects of case classes, - // unless they exist already - Namers.this.caseClassOfModuleClass get clazz match { - case Some(cdef) => - val go = if (inIDE) { // garbage collect in the presentaiton compiler. - assert(cdef.symbol != null && cdef.symbol != NoSymbol) - if (!cdef.symbol.isClass || !cdef.symbol.hasFlag(CASE) || cdef.symbol.rawInfo == NoType) false - else true - } else true - if (go) - addApplyUnapply(cdef, templateNamer) - if (!go || !inIDE) caseClassOfModuleClass -= clazz - if (!go) { - val rem = clazz.linkedModuleOfClass - assert(rem != NoSymbol) - } - case None => - } - ClassInfoType(parents, decls, clazz) - } - - private def classSig(tparams: List[TypeDef], impl: Template): Type = - polyType(typer.reenterTypeParams(tparams), templateSig(impl)) - - private def methodSig(tparams: List[TypeDef], vparamss: List[List[ValDef]], - tpt: Tree, rhs: Tree): Type = { - val meth = context.owner - - val tparamSyms = typer.reenterTypeParams(tparams) - var vparamSymss = - if (inIDE && meth.isPrimaryConstructor) { - // @S: because they have already been entered this way.... - - enterValueParams(meth.owner.owner, vparamss) - } else { - enterValueParams(meth, vparamss) - } - if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) { - tpt.tpe = context.enclClass.owner.tpe - tpt setPos meth.pos - } - - if (onlyPresentation && methodArgumentNames != null) - methodArgumentNames(meth) = vparamss.map(_.map(_.symbol)); - - def convertToDeBruijn(vparams: List[Symbol], level: Int): TypeMap = new TypeMap { - def debruijnFor(param: Symbol) = - DeBruijnIndex(level, vparams indexOf param) - def apply(tp: Type) = { - tp match { - case SingleType(_, sym) => - if (settings.Xexperimental.value && sym.owner == meth && (vparams contains sym)) { -/* - if (sym hasFlag IMPLICIT) { - context.error(sym.pos, "illegal type dependence on implicit parameter") - ErrorType - } else -*/ - debruijnFor(sym) - } else tp - case MethodType(formals, restpe) => - val formals1 = List.mapConserve(formals)(this) - val restpe1 = convertToDeBruijn(vparams, level + 1)(restpe) - if ((formals1 eq formals) && (restpe1 eq restpe)) tp - else copyMethodType(tp, formals1, restpe1) - case _ => - mapOver(tp) - } - } - - object treeTrans extends TypeMapTransformer { - override def transform(tree: Tree): Tree = - tree match { - case Ident(name) if (vparams contains tree.symbol) => - val dtpe = debruijnFor(tree.symbol) - val dsym = - newLocalDummy(context.owner, tree.symbol.pos) - .newValue(tree.symbol.pos, name) - - dsym.setFlag(PARAM) - dsym.setInfo(dtpe) - Ident(name).setSymbol(dsym).copyAttrs(tree).setType(dtpe) - case tree => super.transform(tree) - } - } - - override def mapOver(arg: Tree) = Some(treeTrans.transform(arg)) - } - - val checkDependencies: TypeTraverser = new TypeTraverser { - def traverse(tp: Type) = { - tp match { - case SingleType(_, sym) => - if (sym.owner == meth && (vparamSymss exists (_ contains sym))) - context.error( - sym.pos, - "illegal dependent method type"+ - (if (settings.Xexperimental.value) - ": parameter appears in the type of another parameter in the same section or an earlier one" - else "")) - case _ => - mapOver(tp) - } - this - } - } - - def makeMethodType(vparams: List[Symbol], restpe: Type) = { - val formals = vparams map (vparam => - if (meth hasFlag JAVA) objToAny(vparam.tpe) else vparam.tpe) - val restpe1 = convertToDeBruijn(vparams, 1)(restpe) - if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT)) - ImplicitMethodType(formals, restpe1) - else if (meth hasFlag JAVA) JavaMethodType(formals, restpe1) - else MethodType(formals, restpe1) - } - - def thisMethodType(restpe: Type) = - polyType( - tparamSyms, - if (vparamSymss.isEmpty) PolyType(List(), restpe) - else checkDependencies((vparamSymss :\ restpe) (makeMethodType))) - - var resultPt = if (tpt.isEmpty) WildcardType else typer.typedType(tpt).tpe - val site = meth.owner.thisType - - def overriddenSymbol = intersectionType(meth.owner.info.parents).member(meth.name).filter(sym => - sym != NoSymbol && (site.memberType(sym) matches thisMethodType(resultPt))) - - // fill in result type and parameter types from overridden symbol if there is a unique one. - if (meth.owner.isClass && (tpt.isEmpty || vparamss.exists(_.exists(_.tpt.isEmpty)))) { - // try to complete from matching definition in base type - for (vparams <- vparamss; vparam <- vparams) - if (vparam.tpt.isEmpty) vparam.symbol setInfo WildcardType - val overridden = overriddenSymbol - if (overridden != NoSymbol && !(overridden hasFlag OVERLOADED)) { - resultPt = site.memberType(overridden) match { - case PolyType(tparams, rt) => rt.substSym(tparams, tparamSyms) - case mt => mt - } - - for (vparams <- vparamss) { - var pfs = resultPt.paramTypes - for (vparam <- vparams) { - if (vparam.tpt.isEmpty) { - vparam.tpt.tpe = pfs.head - vparam.tpt setPos vparam.pos - vparam.symbol setInfo pfs.head - } - pfs = pfs.tail - } - resultPt = resultPt.resultType - } - resultPt match { - case PolyType(List(), rtpe) => resultPt = rtpe - case MethodType(List(), rtpe) => resultPt = rtpe - case _ => - } - if (tpt.isEmpty) { - // provisionally assign `meth' a method type with inherited result type - // that way, we can leave out the result type even if method is recursive. - meth setInfo thisMethodType(resultPt) - } - } - } - // Add a () parameter section if this overrides dome method with () parameters. - if (meth.owner.isClass && vparamss.isEmpty && overriddenSymbol.alternatives.exists( - _.info.isInstanceOf[MethodType])) { - vparamSymss = List(List()) - } - for (vparams <- vparamss; vparam <- vparams if vparam.tpt.isEmpty) { - context.error(vparam.pos, "missing parameter type") - vparam.tpt.tpe = ErrorType - } - - thisMethodType( - if (tpt.isEmpty) { - val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol)) - tpt.tpe = widenIfNotFinal(meth, typer.computeType(rhs, pt), pt) - tpt setPos meth.pos - tpt.tpe - } else typer.typedType(tpt).tpe) - } - - //@M! an abstract type definition (abstract type member/type parameter) may take type parameters, which are in scope in its bounds - private def typeDefSig(tpsym: Symbol, tparams: List[TypeDef], rhs: Tree) = { - val tparamSyms = typer.reenterTypeParams(tparams) //@M make tparams available in scope (just for this abstypedef) - val tp = typer.typedType(rhs).tpe match { - case TypeBounds(lt, rt) if (lt.isError || rt.isError) => - TypeBounds(NothingClass.tpe, AnyClass.tpe) - case tp @ TypeBounds(lt, rt) if (tpsym hasFlag JAVA) => - TypeBounds(lt, objToAny(rt)) - case tp => - tp - } - - def verifyOverriding(other: Symbol): Boolean = { - if(other.unsafeTypeParams.length != tparamSyms.length) { - context.error(tpsym.pos, - "The kind of "+tpsym.keyString+" "+tpsym.varianceString + tpsym.nameString+ - " does not conform to the expected kind of " + other.defString + other.locationString + ".") - false - } else true - } - - // @M: make sure overriding in refinements respects rudimentary kinding - // have to do this early, as otherwise we might get crashes: (see neg/bug1275.scala) - // suppose some parameterized type member is overridden by a type member w/o params, - // then appliedType will be called on a type that does not expect type args --> crash - if (tpsym.owner.isRefinementClass && // only needed in refinements - !tpsym.allOverriddenSymbols.forall{verifyOverriding(_)}) - ErrorType - else polyType(tparamSyms, tp) - } - - /** Given a case class - * - * case class C[Ts] (ps: Us) - * - * Add the following methods to toScope: - * - * 1. if case class is not abstract, add - * - * <synthetic> <case> def apply[Ts](ps: Us): C[Ts] = new C[Ts](ps) - * - * 2. add a method - * - * <synthetic> <case> def unapply[Ts](x: C[Ts]) = <ret-val> - * - * where <ret-val> is the caseClassUnapplyReturnValue of class C (see UnApplies.scala) - */ - def addApplyUnapply(cdef: ClassDef, namer: Namer) { - if (!(cdef.symbol hasFlag ABSTRACT)) - namer.enterSyntheticSym(caseModuleApplyMeth(cdef)) - namer.enterSyntheticSym(caseModuleUnapplyMeth(cdef)) - } - - def typeSig(tree: Tree): Type = { - val sym: Symbol = tree.symbol - tree match { - case defn: MemberDef => - val ainfos = for { - annot <- defn.mods.annotations - val ainfo = typer.typedAnnotation(annot, tree.symbol) - if !ainfo.atp.isError && annot != null - } yield ainfo - if (!ainfos.isEmpty) { - val annotated = if (sym.isModule) sym.moduleClass else sym - annotated.attributes = ainfos - } - case _ => - } - implicit val scopeKind = TypeSigScopeKind - val result = - try { - tree match { - case ClassDef(_, _, tparams, impl) => - newNamer(context.makeNewScope(tree, sym)).classSig(tparams, impl) - - case ModuleDef(_, _, impl) => - val clazz = sym.moduleClass - clazz.setInfo(newNamer(context.makeNewScope(tree, clazz)).templateSig(impl)) - //clazz.typeOfThis = singleType(sym.owner.thisType, sym); - clazz.tpe - - case DefDef(_, _, tparams, vparamss, tpt, rhs) => - //val result = - newNamer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs) - - case vdef @ ValDef(mods, _, tpt, rhs) => - val typer1 = typer.constrTyperIf(sym.hasFlag(PARAM | PRESUPER) && sym.owner.isConstructor) - if (tpt.isEmpty) { - if (rhs.isEmpty) { - context.error(tpt.pos, "missing parameter type"); - ErrorType - } else { - tpt.tpe = widenIfNotFinal( - sym, - newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType), - WildcardType) - tpt setPos vdef.pos - tpt.tpe - } - } else typer1.typedType(tpt).tpe - - case TypeDef(_, _, tparams, rhs) => - newNamer(context.makeNewScope(tree, sym)).typeDefSig(sym, tparams, rhs) //@M! - - case Import(expr, selectors) => - val expr1 = typer.typedQualifier(expr) - val base = expr1.tpe - typer.checkStable(expr1) - if (expr1.symbol.isRootPackage) context.error(tree.pos, "_root_ cannot be imported") - def checkNotRedundant(pos: Position, from: Name, to: Name): Boolean = { - if (!tree.symbol.hasFlag(SYNTHETIC) && - !((expr1.symbol ne null) && expr1.symbol.isInterpreterWrapper) && - base.member(from) != NoSymbol) { - val e = context.scope.lookupEntryWithContext(to)(context.owner) - def warnRedundant(sym: Symbol) = - context.unit.warning(pos, "imported `"+to+ - "' is permanently hidden by definition of "+sym+ - sym.locationString) - if ((e ne null) && e.owner == context.scope) { - warnRedundant(e.sym); return false - } else if (context eq context.enclClass) { - val defSym = context.prefix.member(to) filter ( - sym => sym.exists && context.isAccessible(sym, context.prefix, false)) - if (defSym != NoSymbol) { warnRedundant(defSym); return false } - } - } - true - } - def checkSelectors(selectors: List[(Name, Name)]): Unit = selectors match { - case (from, to) :: rest => - if (from != nme.WILDCARD && base != ErrorType) { - if (base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol) - context.error(tree.pos, from.decode + " is not a member of " + expr); - if (checkNotRedundant(tree.pos, from, to)) - checkNotRedundant(tree.pos, from.toTypeName, to.toTypeName) - } - if (from != nme.WILDCARD && (rest.exists (sel => sel._1 == from))) - context.error(tree.pos, from.decode + " is renamed twice"); - if ((to ne null) && to != nme.WILDCARD && (rest exists (sel => sel._2 == to))) - context.error(tree.pos, to.decode + " appears twice as a target of a renaming"); - checkSelectors(rest) - case Nil => - } - checkSelectors(selectors) - ImportType(expr1) - } - } catch { - case ex: TypeError => - //Console.println("caught " + ex + " in typeSig")//DEBUG - typer.reportTypeError(tree.pos, ex) - ErrorType - } - result match { - case PolyType(tparams, restpe) - if (!tparams.isEmpty && tparams.head.owner.isTerm || - // Adriaan: The added conditon below is quite a hack. It seems that HK type parameters is relying - // on a pass that forces all infos in the type to get everything right. - // The problem is that the same pass causes cyclic reference errors in - // test pos/cyclics.scala. It turned out that deSkolemize is run way more often than necessary, - // ruinning it only when needed fixes the cuclic reference errors. - // But correcting deSkolemize broke HK types, because we don't do the traversal anymore. - // For the moment I made a special hack to do the traversal if we have HK type parameters. - // Maybe it's not a hack, then we need to document it better. But ideally, we should find - // a way to deal with HK types that's not dependent on accidental side - // effects like this. - tparams.exists(!_.typeParams.isEmpty)) => - new DeSkolemizeMap(tparams) mapOver result - case _ => -// println("not skolemizing "+result+" in "+context.owner) -// new DeSkolemizeMap(List()) mapOver result - result - } - } - - /** Check that symbol's definition is well-formed. This means: - * - no conflicting modifiers - * - `abstract' modifier only for classes - * - `override' modifier never for classes - * - `def' modifier never for parameters of case classes - * - declarations only in mixins or abstract classes (when not @native) - */ - def validate(sym: Symbol) { - def checkNoConflict(flag1: Int, flag2: Int) { - if (sym.hasFlag(flag1) && sym.hasFlag(flag2)) - context.error(sym.pos, - if (flag1 == DEFERRED) - "abstract member may not have " + Flags.flagsToString(flag2) + " modifier"; - else - "illegal combination of modifiers: " + - Flags.flagsToString(flag1) + " and " + Flags.flagsToString(flag2) + - " for: " + sym + Flags.flagsToString(sym.rawflags)); - } - - if (sym.hasFlag(IMPLICIT) && !sym.isTerm) - context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods") - if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass && !inIDE) - context.error(sym.pos, "`implicit' modifier cannot be used for top-level objects") - if (sym.hasFlag(ABSTRACT) && !sym.isClass) - context.error(sym.pos, "`abstract' modifier can be used only for classes; " + - "\nit should be omitted for abstract members") - if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && !sym.hasFlag(TRAIT) && sym.isClass) - context.error(sym.pos, "`override' modifier not allowed for classes") - if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isConstructor) - context.error(sym.pos, "`override' modifier not allowed for constructors") - if (sym.hasFlag(ABSOVERRIDE) && !sym.owner.isTrait) - context.error(sym.pos, "`abstract override' modifier only allowed for members of traits") - if (sym.hasFlag(LAZY) && sym.hasFlag(PRESUPER)) - context.error(sym.pos, "`lazy' definitions may not be initialized early") - if (sym.info.typeSymbol == FunctionClass(0) && - 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 hasFlag DEFERRED) { // virtual classes count, too - if (sym.hasAttribute(definitions.NativeAttr)) - sym.resetFlag(DEFERRED) - else 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)) - sym.resetFlag(DEFERRED) - } - } - - checkNoConflict(DEFERRED, PRIVATE) - checkNoConflict(FINAL, SEALED) - checkNoConflict(PRIVATE, PROTECTED) - checkNoConflict(PRIVATE, OVERRIDE) - /* checkNoConflict(PRIVATE, FINAL) // can't do this because FINAL also means compile-time constant */ - checkNoConflict(DEFERRED, FINAL) - } - } - - abstract class TypeCompleter extends LazyType { - val tree: Tree - } - - def mkTypeCompleter(t: Tree)(c: Symbol => Unit) = new TypeCompleter { - val tree = t - override def complete(sym: Symbol) = c(sym) - } - - /** A class representing a lazy type with known type parameters. - */ - class PolyTypeCompleter(tparams: List[Tree], restp: TypeCompleter, owner: Tree, ownerSym: Symbol, ctx: Context) extends TypeCompleter { - override val typeParams: List[Symbol]= tparams map (_.symbol) //@M - override val tree = restp.tree - override def complete(sym: Symbol) { - if(ownerSym.isAbstractType) //@M an abstract type's type parameters are entered -- TODO: change to isTypeMember ? - newNamer(ctx.makeNewScope(owner, ownerSym)(PolyTypeCompleterScopeKind)).enterSyms(tparams) //@M - restp.complete(sym) - } - } - - /** The symbol that which this accessor represents (possibly in part). - * This is used for error messages, where we want to speak in terms - * of the actual declaration or definition, not in terms of the generated setters - * and getters */ - def underlying(member: Symbol): Symbol = - if (member hasFlag ACCESSOR) { - if (member.isDeferred) { - val getter = if (member.isSetter) member.getter(member.owner) else member - if (inIDE && getter == NoSymbol) return NoSymbol; - val result = getter.owner.newValue(getter.pos, getter.name) - .setInfo(getter.tpe.resultType) - .setFlag(DEFERRED) - if (getter.setter(member.owner) != NoSymbol) result.setFlag(MUTABLE) - result - } else member.accessed - } else member - - /** An explanatory note to be added to error messages - * when there's a problem with abstract var defs */ - def varNotice(sym: Symbol): String = - if (underlying(sym).isVariable) - "\n(Note that variables need to be initialized to be defined)" - else "" -} - diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala.2 b/src/compiler/scala/tools/nsc/typechecker/Namers.scala.2 deleted file mode 100755 index bffde363c0..0000000000 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala.2 +++ /dev/null @@ -1,1046 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2009 LAMP/EPFL - * @author Martin Odersky - */ -// $Id: Namers.scala 17114 2009-02-15 16:43:36Z odersky $ - -package scala.tools.nsc.typechecker - -import scala.collection.mutable.HashMap -import scala.tools.nsc.util.Position -import symtab.Flags -import symtab.Flags._ - -/** This trait declares methods to create symbols and to enter them into scopes. - * - * @author Martin Odersky - * @version 1.0 - */ -trait Namers { self: Analyzer => - import global._ - import definitions._ - import posAssigner.atPos - - /** Convert to corresponding type parameters all skolems of method parameters - * which appear in `tparams`. - */ - class DeSkolemizeMap(tparams: List[Symbol]) extends TypeMap { - def apply(tp: Type): Type = tp match { - case TypeRef(pre, sym, args) - if (sym.isTypeSkolem && (tparams contains sym.deSkolemize)) => -// println("DESKOLEMIZING "+sym+" in "+sym.owner) - mapOver(rawTypeRef(NoPrefix, sym.deSkolemize, args)) -/* - case PolyType(tparams1, restpe) => - new DeSkolemizeMap(tparams1 ::: tparams).mapOver(tp) - case ClassInfoType(parents, decls, clazz) => - val parents1 = List.mapConserve(parents)(this) - if (parents1 eq parents) tp else ClassInfoType(parents1, decls, clazz) -*/ - case _ => - mapOver(tp) - } - } - - private class NormalNamer(context : Context) extends Namer(context) - def newNamer(context : Context) : Namer = new NormalNamer(context) - - private[typechecker] val caseClassOfModuleClass = new HashMap[Symbol, ClassDef] - - def resetNamer() { - caseClassOfModuleClass.clear - } - - abstract class Namer(val context: Context) { - - val typer = newTyper(context) - - def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym = { - if (!mods.privateWithin.isEmpty) - sym.privateWithin = typer.qualifyingClassContext(tree, mods.privateWithin, true).owner - sym - } - - def inConstructorFlag: Long = - if (context.owner.isConstructor && !context.inConstructorSuffix || context.owner.isEarly) INCONSTRUCTOR - else 0l - - def moduleClassFlags(moduleFlags: Long) = - (moduleFlags & ModuleToClassFlags) | FINAL | inConstructorFlag - - def updatePosFlags(sym: Symbol, pos: Position, flags: Long): Symbol = { - if (settings.debug.value) log("overwriting " + sym) - val lockedFlag = sym.flags & LOCKED - sym.reset(NoType) - sym setPos pos - sym.flags = flags | lockedFlag - if (sym.isModule && sym.moduleClass != NoSymbol) - updatePosFlags(sym.moduleClass, pos, moduleClassFlags(flags)) - if (sym.owner.isPackageClass && - (sym.linkedSym.rawInfo.isInstanceOf[loaders.SymbolLoader] || - sym.linkedSym.rawInfo.isComplete && runId(sym.validTo) != currentRunId)) - // pre-set linked symbol to NoType, in case it is not loaded together with this symbol. - sym.linkedSym.setInfo(NoType) - sym - } - - private def isTemplateContext(context: Context): Boolean = context.tree match { - case Template(_, _, _) => true - case Import(_, _) => isTemplateContext(context.outer) - case _ => false - } - - private var innerNamerCache: Namer = null - protected def makeConstructorScope(classContext : Context) : Context = { - val outerContext = classContext.outer.outer - outerContext.makeNewScope(outerContext.tree, outerContext.owner)(Constructor1ScopeKind) - } - - def namerOf(sym: Symbol): Namer = { - - def innerNamer: Namer = { - if (innerNamerCache eq null) - innerNamerCache = - if (!isTemplateContext(context)) this - else newNamer(context.make(context.tree, context.owner, scopeFor(context.tree, InnerScopeKind))) - innerNamerCache - } - - def primaryConstructorParamNamer: Namer = { //todo: can we merge this with SCCmode? - val classContext = context.enclClass - val paramContext = makeConstructorScope(classContext) - val unsafeTypeParams = context.owner.unsafeTypeParams - unsafeTypeParams foreach(sym => paramContext.scope.enter(sym)) - newNamer(paramContext) - } - if (sym.isTerm) { - if (sym.hasFlag(PARAM) && sym.owner.isPrimaryConstructor) - primaryConstructorParamNamer - else if (sym.hasFlag(PARAMACCESSOR) && !inIDE) - primaryConstructorParamNamer - else innerNamer - } else innerNamer - } - - protected def conflict(newS : Symbol, oldS : Symbol) : Boolean = { - (!oldS.isSourceMethod || - nme.isSetterName(newS.name) || - newS.owner.isPackageClass) && - !((newS.owner.isTypeParameter || newS.owner.isAbstractType) && - newS.name.length==1 && newS.name(0)=='_') //@M: allow repeated use of `_' for higher-order type params - } - - // IDE hook - protected def setInfo[Sym <: Symbol](sym : Sym)(tpe : LazyType) : Sym = sym.setInfo(tpe) - - private def doubleDefError(pos: Position, sym: Symbol) { - context.error(pos, - sym.name.toString() + " is already defined as " + - (if (sym.hasFlag(SYNTHETIC)) - "(compiler-generated) "+ (if (sym.isModule) "case class companion " else "") - else "") + - (if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString())) - } - - private def inCurrentScope(m: Symbol): Boolean = { - if (context.owner.isClass) context.owner == m.owner - else m.owner.isClass && context.scope == m.owner.info.decls - } - - def enterInScope(sym: Symbol): Symbol = enterInScope(sym, context.scope) - - def enterInScope(sym: Symbol, scope: Scope): Symbol = { - // allow for overloaded methods - if (!(sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass)) { - var prev = scope.lookupEntryWithContext(sym.name)(context.owner); - if ((prev ne null) && inIDE) { - var guess = prev - while ((guess ne null) && (guess.sym ne sym)) guess = scope.lookupNextEntry(guess) - if (guess != null) prev = guess - while (prev != null && (!prev.sym.hasRawInfo || !prev.sym.rawInfo.isComplete || - (prev.sym.sourceFile == null && sym.getClass == prev.sym.getClass))) { - if (!prev.sym.hasRawInfo || prev.sym.rawInfo.isComplete) { - Console.println("DITCHING: " + prev.sym) - } - scope unlink prev.sym - prev = scope.lookupNextEntry(prev) - } - val sym0 = scope enter sym - if (sym0 ne sym) { - Console.println("WEIRD: " + sym0 + " vs. " + sym + " " + sym0.id + " " + sym.id + " " + sym.sourceFile + " " + sym0.sourceFile) - } - if (prev != null && (sym0 ne prev.sym) && conflict(sym0,prev.sym)) { - doubleDefError(sym0.pos, prev.sym) - } - sym0 - } else if ((prev ne null) && prev.owner == scope && conflict(sym, prev.sym)) { - doubleDefError(sym.pos, prev.sym) - sym setInfo ErrorType // don't do this in IDE for stability - scope unlink prev.sym // let them co-exist... - scope enter sym - } else scope enter sym - } else scope enter sym - } - - def enterPackageSymbol(pos: Position, name: Name): Symbol = { - val (cscope, cowner) = - if (context.owner == EmptyPackageClass) (RootClass.info.decls, RootClass) - else (context.scope, context.owner) - val p: Symbol = cscope.lookupWithContext(name)(context.owner) - if (p.isPackage && cscope == p.owner.info.decls) { - p - } else { - val pkg = cowner.newPackage(pos, name) - // IDE: newScope should be ok because packages are never destroyed. - if (inIDE) assert(!pkg.moduleClass.hasRawInfo || !pkg.moduleClass.rawInfo.isComplete) - pkg.moduleClass.setInfo(new PackageClassInfoType(newScope, pkg.moduleClass, null)) - pkg.setInfo(pkg.moduleClass.tpe) - enterInScope(pkg, cscope) - } - } - - def enterClassSymbol(tree : ClassDef): Symbol = { - var c: Symbol = context.scope.lookupWithContext(tree.name)(context.owner); - if (!inIDE && c.isType && c.owner.isPackageClass && context.scope == c.owner.info.decls && !currentRun.compiles(c)) { - updatePosFlags(c, tree.pos, tree.mods.flags) - setPrivateWithin(tree, c, tree.mods) - } else { - var sym = context.owner.newClass(tree.pos, tree.name) - sym = sym.setFlag(tree.mods.flags | inConstructorFlag) - sym = setPrivateWithin(tree, sym, tree.mods) - c = enterInScope(sym) - } - if (c.owner.isPackageClass) { - val file = context.unit.source.file - val clazz = c.asInstanceOf[ClassSymbol] - if (settings.debug.value && (clazz.sourceFile ne null) && !clazz.sourceFile.equals(file)) { - Console.err.println("SOURCE MISMATCH: " + clazz.sourceFile + " vs. " + file + " SYM=" + c); - } - clazz.sourceFile = file - if (clazz.sourceFile ne null) { - assert(inIDE || !currentRun.compiles(clazz) || clazz.sourceFile == currentRun.symSource(c)); - currentRun.symSource(c) = clazz.sourceFile - } - } - assert(c.name.toString.indexOf('(') == -1) - c - } - - /** Enter a module symbol. The tree parameter can be either a module definition - * or a class definition */ - def enterModuleSymbol(tree : ModuleDef): Symbol = { - // .pos, mods.flags | MODULE | FINAL, name - var m: Symbol = context.scope.lookupWithContext(tree.name)(context.owner) - val moduleFlags = tree.mods.flags | MODULE | FINAL - if (m.isModule && !m.isPackage && inCurrentScope(m) && - ((!inIDE && !currentRun.compiles(m)) || (m hasFlag SYNTHETIC))) { - updatePosFlags(m, tree.pos, moduleFlags) - setPrivateWithin(tree, m, tree.mods) - context.unit.synthetics -= m - } else { - m = context.owner.newModule(tree.pos, tree.name) - m.setFlag(moduleFlags) - m = setPrivateWithin(tree, m, tree.mods) - m = enterInScope(m) - - m.moduleClass.setFlag(moduleClassFlags(moduleFlags)) - setPrivateWithin(tree, m.moduleClass, tree.mods) - } - if (m.owner.isPackageClass) { - m.moduleClass.sourceFile = context.unit.source.file - currentRun.symSource(m) = m.moduleClass.sourceFile - } - m - } - - def enterSyms(trees: List[Tree]): Namer = { - var namer : Namer = this - for (tree <- trees) { - val txt = namer.enterSym(tree) - if (!(txt eq namer.context)) namer = newNamer(txt) - } - namer - } - - def newTypeSkolems(tparams: List[Symbol]): List[Symbol] = { - val tskolems = tparams map (_.newTypeSkolem) - val ltp = new LazyType { - override def complete(sym: Symbol) { - sym setInfo sym.deSkolemize.info.substSym(tparams, tskolems) //@M the info of a skolem is the skolemized info of the actual type parameter of the skolem - } - } - tskolems foreach (_.setInfo(ltp)) - tskolems - } - - /** Replace type parameters with their TypeSkolems, which can later be deskolemized to the original type param - * (a skolem is a representation of a bound variable when viewed inside its scope) - */ - def skolemize(tparams: List[TypeDef]) { - val tskolems = newTypeSkolems(tparams map (_.symbol)) - for ((tparam, tskolem) <- tparams zip tskolems) tparam.symbol = tskolem - } - - def applicableTypeParams(owner: Symbol): List[Symbol] = - if (inIDE && (owner eq NoSymbol)) List() - else if (owner.isTerm || owner.isPackageClass) List() - else applicableTypeParams(owner.owner) ::: owner.typeParams - - def enterSym(tree: Tree): Context = try { - - def finishWith(tparams: List[TypeDef]) { - val sym = tree.symbol - if (settings.debug.value) log("entered " + sym + " in " + context.owner + ", scope-id = " + context.scope.hashCode()); - var ltype = namerOf(sym).typeCompleter(tree) - if (!tparams.isEmpty) { - //@M! TypeDef's type params are handled differently - //@M e.g., in [A[x <: B], B], A and B are entered first as both are in scope in the definition of x - //@M x is only in scope in `A[x <: B]' - if(!sym.isAbstractType) //@M TODO: change to isTypeMember ? - newNamer(context.makeNewScope(tree, sym)(FinishWithScopeKind)).enterSyms(tparams) - ltype = new PolyTypeCompleter(tparams, ltype, tree, sym, context) //@M - if (sym.isTerm) skolemize(tparams) - } - setInfo(sym)(ltype) - } - def finish = finishWith(List()) - - if (tree.symbol == NoSymbol) { - val owner = context.owner - tree match { - case PackageDef(name, stats) => - tree.symbol = enterPackageSymbol(tree.pos, name) - val namer = newNamer( - context.make(tree, tree.symbol.moduleClass, tree.symbol.info.decls)) - namer.enterSyms(stats) - case tree @ ClassDef(mods, name, tparams, impl) => - tree.symbol = enterClassSymbol(tree) - finishWith(tparams) - if ((mods.flags & CASE) != 0) { - var m: Symbol = context.scope.lookupWithContext(tree.name.toTermName)(context.owner).filter(! _.isSourceMethod) - if (!(m.isModule && inCurrentScope(m) && (inIDE || currentRun.compiles(m)))) { - m = enterSyntheticSym(caseModuleDef(tree)) - } - caseClassOfModuleClass(m.moduleClass) = tree - } - case tree @ ModuleDef(mods, name, _) => - tree.symbol = enterModuleSymbol(tree) - tree.symbol.moduleClass.setInfo(namerOf(tree.symbol).moduleClassTypeCompleter((tree))) - finish - - case ValDef(mods, name, tp, rhs) => - if ((!context.owner.isClass || - (mods.flags & (PRIVATE | LOCAL)) == (PRIVATE | LOCAL) || - name.endsWith(nme.OUTER, nme.OUTER.length) || - context.unit.isJava) && - (mods.flags & LAZY) == 0) { - tree.symbol = enterInScope(owner.newValue(tree.pos, name) - .setFlag(mods.flags)) - finish - } else { - // add getter and possibly also setter - val accflags: Long = ACCESSOR | - (if ((mods.flags & MUTABLE) != 0) mods.flags & ~MUTABLE & ~PRESUPER - else mods.flags & ~PRESUPER | STABLE) - if (nme.isSetterName(name)) - context.error(tree.pos, "Names of vals or vars may not end in `_='") - var getter = owner.newMethod(tree.pos, name).setFlag(accflags) - setPrivateWithin(tree, getter, mods) - getter = enterInScope(getter).asInstanceOf[TermSymbol] - setInfo(getter)(namerOf(getter).getterTypeCompleter(tree)) - if ((mods.flags & MUTABLE) != 0) { - var setter = owner.newMethod(tree.pos, nme.getterToSetter(name)) - .setFlag(accflags & ~STABLE & ~CASEACCESSOR) - setPrivateWithin(tree, setter, mods) - setter = enterInScope(setter).asInstanceOf[TermSymbol] - setInfo(setter)(namerOf(setter).setterTypeCompleter(tree)) - } - tree.symbol = - if ((mods.flags & DEFERRED) == 0) { - var vsym = - if (!context.owner.isClass) { - assert((mods.flags & LAZY) != 0) // if not a field, it has to be a lazy val - owner.newValue(tree.pos, name + "$lzy" ).setFlag(mods.flags | MUTABLE) - } else { - owner.newValue(tree.pos, nme.getterToLocal(name)) - .setFlag(mods.flags & FieldFlags | PRIVATE | LOCAL | (if ((mods.flags & LAZY) != 0) MUTABLE else 0)) - } - vsym = enterInScope(vsym).asInstanceOf[TermSymbol] - setInfo(vsym)(namerOf(vsym).typeCompleter(tree)) - if ((mods.flags & LAZY) != 0) - vsym.setLazyAccessor(getter) - vsym - } else getter - } - case DefDef(mods, nme.CONSTRUCTOR, tparams, _, _, _) => - var sym = owner.newConstructor(tree.pos).setFlag(mods.flags | owner.getFlag(ConstrFlags)) - setPrivateWithin(tree, sym, mods) - tree.symbol = enterInScope(sym) - finishWith(tparams) - case DefDef(mods, name, tparams, _, _, _) => - var sym = (owner.newMethod(tree.pos, name)).setFlag(mods.flags) - setPrivateWithin(tree, sym, mods) - tree.symbol = enterInScope(sym) - finishWith(tparams) - case TypeDef(mods, name, tparams, _) => - var flags: Long = mods.flags - if ((flags & PARAM) != 0) flags |= DEFERRED - var sym = new TypeSymbol(owner, tree.pos, name).setFlag(flags) - setPrivateWithin(tree, sym, mods) - tree.symbol = enterInScope(sym) - finishWith(tparams) - case DocDef(_, defn) => - enterSym(defn) - case imp @ Import(_, _) => - tree.symbol = NoSymbol.newImport(tree.pos) - setInfo(tree.symbol)(namerOf(tree.symbol).typeCompleter(tree)) - return (context.makeNewImport(imp)) - case _ => - } - } - this.context - } catch { - case ex: TypeError => - //Console.println("caught " + ex + " in enterSym")//DEBUG - typer.reportTypeError(tree.pos, ex) - this.context - } - - def enterSyntheticSym(tree: Tree): Symbol = { - enterSym(tree) - context.unit.synthetics(tree.symbol) = tree - tree.symbol - } - -// --- Lazy Type Assignment -------------------------------------------------- - - def typeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => - if (settings.debug.value) log("defining " + sym + Flags.flagsToString(sym.flags)+sym.locationString) - val tp = typeSig(tree) - tp match { - case TypeBounds(lo, hi) => - // check that lower bound is not an F-bound - for (val t <- lo) { - t match { - case TypeRef(_, sym, _) => sym.initialize - case _ => - } - } - case _ => - } - sym.setInfo(tp) - if ((sym.isAliasType || sym.isAbstractType) && !(sym hasFlag PARAM) && - !typer.checkNonCyclic(tree.pos, tp)) - sym.setInfo(ErrorType) // this early test is there to avoid infinite baseTypes when - // adding setters and getters --> bug798 - if (settings.debug.value) log("defined " + sym); - validate(sym) - } - - def moduleClassTypeCompleter(tree: Tree) = { - mkTypeCompleter(tree) { sym => - val moduleSymbol = tree.symbol - assert(moduleSymbol.moduleClass == sym) - if (inIDE && moduleSymbol.rawInfo.isComplete) { - // reset! - } - moduleSymbol.info // sets moduleClass info as a side effect. - //assert(sym.rawInfo.isComplete) - } - } - - def getterTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => - if (settings.debug.value) log("defining " + sym) - sym.setInfo(PolyType(List(), typeSig(tree))) - if (settings.debug.value) log("defined " + sym) - validate(sym) - } - - def setterTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => - if (settings.debug.value) log("defining " + sym); - sym.setInfo(MethodType(List(typeSig(tree)), UnitClass.tpe)) - if (settings.debug.value) log("defined " + sym); - validate(sym) - } - - def selfTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => - var selftpe = typer.typedType(tree).tpe - if (!(selftpe.typeSymbol isNonBottomSubClass sym.owner)) - selftpe = intersectionType(List(sym.owner.tpe, selftpe)) -// println("completing self of "+sym.owner+": "+selftpe) - sym.setInfo(selftpe) - } - - private def widenIfNotFinal(sym: Symbol, tpe: Type, pt: Type): Type = { - val getter = - if (sym.isValue && sym.owner.isClass && (sym hasFlag PRIVATE)) - sym.getter(sym.owner) - else sym - def isHidden(tp: Type): Boolean = tp match { - case SingleType(pre, sym) => - (sym isLessAccessibleThan getter) || isHidden(pre) - case ThisType(sym) => - sym isLessAccessibleThan getter - case p: SimpleTypeProxy => - isHidden(p.underlying) - case _ => - false - } - val tpe1 = tpe.deconst - val tpe2 = tpe1.widen - if ((sym.isVariable || sym.isMethod && !(sym hasFlag ACCESSOR))) - if (tpe2 <:< pt) tpe2 else tpe1 - else if (isHidden(tpe)) tpe2 - else if (!(sym hasFlag FINAL)) tpe1 - else tpe - } - - def enterValueParams(owner: Symbol, vparamss: List[List[ValDef]]): List[List[Symbol]] = { - def enterValueParam(param: ValDef): Symbol = { - if (inIDE) param.symbol = { - var sym = owner.newValueParameter(param.pos, param.name). - setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT)) - setPrivateWithin(param, sym, param.mods) - sym = enterInScope(sym).asInstanceOf[TermSymbol] - if (!sym.hasRawInfo || sym.rawInfo.isComplete) - setInfo(sym)(typeCompleter(param)) - sym - } else param.symbol = setInfo( - enterInScope{ - val sym = owner.newValueParameter(param.pos, param.name). - setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT)) - setPrivateWithin(param, sym, param.mods) - })(typeCompleter(param)) - param.symbol - } - vparamss.map(_.map(enterValueParam)) - } - - private def templateSig(templ: Template): Type = { - val clazz = context.owner - def checkParent(tpt: Tree): Type = { - val tp = tpt.tpe - if (tp.typeSymbol == context.owner) { - context.error(tpt.pos, ""+tp.typeSymbol+" inherits itself") - AnyRefClass.tpe - } else if (tp.isError) { - AnyRefClass.tpe - } else { - tp - } - } - def enterSelf(self: ValDef) { - if (!self.tpt.isEmpty) { - clazz.typeOfThis = selfTypeCompleter(self.tpt) - self.symbol = clazz.thisSym.setPos(self.pos) - } else { - self.tpt.tpe = NoType - if (self.name != nme.WILDCARD) { - clazz.typeOfThis = clazz.tpe - self.symbol = clazz.thisSym - } else if (self ne emptyValDef) { - self.symbol = clazz.newThisSym(self.pos) setInfo clazz.tpe - } - } - if (self.name != nme.WILDCARD) { - self.symbol.name = self.name - self.symbol = context.scope enter self.symbol - } - } - var parents = typer.parentTypes(templ) map checkParent - enterSelf(templ.self) - val decls = newClassScope(clazz) - val templateNamer = newNamer(context.make(templ, clazz, decls)) - .enterSyms(templ.body) - - /* add overridden virtuals to parents - val overridden = clazz.overriddenVirtuals - if (!overridden.isEmpty) - parents = parents ::: ( overridden map ( - sym => TypeRef(clazz.owner.thisType, sym, clazz.typeParams map (_.tpe)))) - println("Parents of "+clazz+":"+parents) - - // check that virtual classses are only defined as members of templates - if (clazz.isVirtualClass && !clazz.owner.isClass) - context.error( - clazz.pos, - "virtual traits and their subclasses must be defined as members of some other class") - - // make subclasses of virtual classes virtual as well; check that - // they are defined in same scope. - val virtualParents = parents map (_.typeSymbol) filter (_.isVirtualClass) - virtualParents find { - vp => !(clazz.owner.isClass && (clazz.owner isSubClass vp.owner)) - } match { - case Some(vp) => - context.error( - clazz.pos, - "subclass of virtual "+vp+ - " needs to be defined at same level,\nas member of "+vp.owner) - case None => - if (!virtualParents.isEmpty) clazz setFlag DEFERRED // make it virtual - } - */ - - // add apply and unapply methods to companion objects of case classes, - // unless they exist already - Namers.this.caseClassOfModuleClass get clazz match { - case Some(cdef) => - val go = if (inIDE) { // garbage collect in the presentaiton compiler. - assert(cdef.symbol != null && cdef.symbol != NoSymbol) - if (!cdef.symbol.isClass || !cdef.symbol.hasFlag(CASE) || cdef.symbol.rawInfo == NoType) false - else true - } else true - if (go) - addApplyUnapply(cdef, templateNamer) - if (!go || !inIDE) caseClassOfModuleClass -= clazz - if (!go) { - val rem = clazz.linkedModuleOfClass - assert(rem != NoSymbol) - } - case None => - } - ClassInfoType(parents, decls, clazz) - } - - private def classSig(tparams: List[TypeDef], impl: Template): Type = - polyType(typer.reenterTypeParams(tparams), templateSig(impl)) - - private def methodSig(tparams: List[TypeDef], vparamss: List[List[ValDef]], - tpt: Tree, rhs: Tree): Type = { - val meth = context.owner - - val tparamSyms = typer.reenterTypeParams(tparams) - var vparamSymss = - if (inIDE && meth.isPrimaryConstructor) { - // @S: because they have already been entered this way.... - - enterValueParams(meth.owner.owner, vparamss) - } else { - enterValueParams(meth, vparamss) - } - if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) { - tpt.tpe = context.enclClass.owner.tpe - tpt setPos meth.pos - } - - if (onlyPresentation && methodArgumentNames != null) - methodArgumentNames(meth) = vparamss.map(_.map(_.symbol)); - - def convertToDeBruijn(vparams: List[Symbol], level: Int): TypeMap = new TypeMap { - def debruijnFor(param: Symbol) = - DeBruijnIndex(level, vparams indexOf param) - def apply(tp: Type) = { - tp match { - case SingleType(_, sym) => - if (settings.Xexperimental.value && sym.owner == meth && (vparams contains sym)) { -/* - if (sym hasFlag IMPLICIT) { - context.error(sym.pos, "illegal type dependence on implicit parameter") - ErrorType - } else -*/ - debruijnFor(sym) - } else tp - case MethodType(formals, restpe) => - val formals1 = List.mapConserve(formals)(this) - val restpe1 = convertToDeBruijn(vparams, level + 1)(restpe) - if ((formals1 eq formals) && (restpe1 eq restpe)) tp - else copyMethodType(tp, formals1, restpe1) - case _ => - mapOver(tp) - } - } - - object treeTrans extends TypeMapTransformer { - override def transform(tree: Tree): Tree = - tree match { - case Ident(name) if (vparams contains tree.symbol) => - val dtpe = debruijnFor(tree.symbol) - val dsym = - newLocalDummy(context.owner, tree.symbol.pos) - .newValue(tree.symbol.pos, name) - - dsym.setFlag(PARAM) - dsym.setInfo(dtpe) - Ident(name).setSymbol(dsym).copyAttrs(tree).setType(dtpe) - case tree => super.transform(tree) - } - } - - override def mapOver(arg: Tree) = Some(treeTrans.transform(arg)) - } - - val checkDependencies: TypeTraverser = new TypeTraverser { - def traverse(tp: Type) = { - tp match { - case SingleType(_, sym) => - if (sym.owner == meth && (vparamSymss exists (_ contains sym))) - context.error( - sym.pos, - "illegal dependent method type"+ - (if (settings.Xexperimental.value) - ": parameter appears in the type of another parameter in the same section or an earlier one" - else "")) - case _ => - mapOver(tp) - } - this - } - } - - def makeMethodType(vparams: List[Symbol], restpe: Type) = { - val formals = vparams map (vparam => - if (meth hasFlag JAVA) objToAny(vparam.tpe) else vparam.tpe) - val restpe1 = convertToDeBruijn(vparams, 1)(restpe) - if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT)) - ImplicitMethodType(formals, restpe1) - else if (meth hasFlag JAVA) JavaMethodType(formals, restpe1) - else MethodType(formals, restpe1) - } - - def thisMethodType(restpe: Type) = - polyType( - tparamSyms, - if (vparamSymss.isEmpty) PolyType(List(), restpe) - else checkDependencies((vparamSymss :\ restpe) (makeMethodType))) - - var resultPt = if (tpt.isEmpty) WildcardType else typer.typedType(tpt).tpe - val site = meth.owner.thisType - - def overriddenSymbol = intersectionType(meth.owner.info.parents).member(meth.name).filter(sym => - sym != NoSymbol && (site.memberType(sym) matches thisMethodType(resultPt))) - - // fill in result type and parameter types from overridden symbol if there is a unique one. - if (meth.owner.isClass && (tpt.isEmpty || vparamss.exists(_.exists(_.tpt.isEmpty)))) { - // try to complete from matching definition in base type - for (vparams <- vparamss; vparam <- vparams) - if (vparam.tpt.isEmpty) vparam.symbol setInfo WildcardType - val overridden = overriddenSymbol - if (overridden != NoSymbol && !(overridden hasFlag OVERLOADED)) { - resultPt = site.memberType(overridden) match { - case PolyType(tparams, rt) => rt.substSym(tparams, tparamSyms) - case mt => mt - } - - for (vparams <- vparamss) { - var pfs = resultPt.paramTypes - for (vparam <- vparams) { - if (vparam.tpt.isEmpty) { - vparam.tpt.tpe = pfs.head - vparam.tpt setPos vparam.pos - vparam.symbol setInfo pfs.head - } - pfs = pfs.tail - } - resultPt = resultPt.resultType - } - resultPt match { - case PolyType(List(), rtpe) => resultPt = rtpe - case MethodType(List(), rtpe) => resultPt = rtpe - case _ => - } - if (tpt.isEmpty) { - // provisionally assign `meth' a method type with inherited result type - // that way, we can leave out the result type even if method is recursive. - meth setInfo thisMethodType(resultPt) - } - } - } - // Add a () parameter section if this overrides dome method with () parameters. - if (meth.owner.isClass && vparamss.isEmpty && overriddenSymbol.alternatives.exists( - _.info.isInstanceOf[MethodType])) { - vparamSymss = List(List()) - } - for (vparams <- vparamss; vparam <- vparams if vparam.tpt.isEmpty) { - context.error(vparam.pos, "missing parameter type") - vparam.tpt.tpe = ErrorType - } - - thisMethodType( - if (tpt.isEmpty) { - val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol)) - tpt.tpe = widenIfNotFinal(meth, typer.computeType(rhs, pt), pt) - tpt setPos meth.pos - tpt.tpe - } else typer.typedType(tpt).tpe) - } - - //@M! an abstract type definition (abstract type member/type parameter) may take type parameters, which are in scope in its bounds - private def typeDefSig(tpsym: Symbol, tparams: List[TypeDef], rhs: Tree) = { - val tparamSyms = typer.reenterTypeParams(tparams) //@M make tparams available in scope (just for this abstypedef) - val tp = typer.typedType(rhs).tpe match { - case TypeBounds(lt, rt) if (lt.isError || rt.isError) => - TypeBounds(NothingClass.tpe, AnyClass.tpe) - case tp @ TypeBounds(lt, rt) if (tpsym hasFlag JAVA) => - TypeBounds(lt, objToAny(rt)) - case tp => - tp - } - - def verifyOverriding(other: Symbol): Boolean = { - if(other.unsafeTypeParams.length != tparamSyms.length) { - context.error(tpsym.pos, - "The kind of "+tpsym.keyString+" "+tpsym.varianceString + tpsym.nameString+ - " does not conform to the expected kind of " + other.defString + other.locationString + ".") - false - } else true - } - - // @M: make sure overriding in refinements respects rudimentary kinding - // have to do this early, as otherwise we might get crashes: (see neg/bug1275.scala) - // suppose some parameterized type member is overridden by a type member w/o params, - // then appliedType will be called on a type that does not expect type args --> crash - if (tpsym.owner.isRefinementClass && // only needed in refinements - !tpsym.allOverriddenSymbols.forall{verifyOverriding(_)}) - ErrorType - else polyType(tparamSyms, tp) - } - - /** Given a case class - * - * case class C[Ts] (ps: Us) - * - * Add the following methods to toScope: - * - * 1. if case class is not abstract, add - * - * <synthetic> <case> def apply[Ts](ps: Us): C[Ts] = new C[Ts](ps) - * - * 2. add a method - * - * <synthetic> <case> def unapply[Ts](x: C[Ts]) = <ret-val> - * - * where <ret-val> is the caseClassUnapplyReturnValue of class C (see UnApplies.scala) - */ - def addApplyUnapply(cdef: ClassDef, namer: Namer) { - if (!(cdef.symbol hasFlag ABSTRACT)) - namer.enterSyntheticSym(caseModuleApplyMeth(cdef)) - namer.enterSyntheticSym(caseModuleUnapplyMeth(cdef)) - } - - def typeSig(tree: Tree): Type = { - val sym: Symbol = tree.symbol - tree match { - case defn: MemberDef => - val ainfos = for { - annot <- defn.mods.annotations - val ainfo = typer.typedAnnotation(annot, tree.symbol) - if !ainfo.atp.isError && annot != null - } yield ainfo - if (!ainfos.isEmpty) { - val annotated = if (sym.isModule) sym.moduleClass else sym - annotated.attributes = ainfos - } - case _ => - } - implicit val scopeKind = TypeSigScopeKind - val result = - try { - tree match { - case ClassDef(_, _, tparams, impl) => - newNamer(context.makeNewScope(tree, sym)).classSig(tparams, impl) - - case ModuleDef(_, _, impl) => - val clazz = sym.moduleClass - clazz.setInfo(newNamer(context.makeNewScope(tree, clazz)).templateSig(impl)) - //clazz.typeOfThis = singleType(sym.owner.thisType, sym); - clazz.tpe - - case DefDef(_, _, tparams, vparamss, tpt, rhs) => - //val result = - newNamer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs) - - case vdef @ ValDef(mods, _, tpt, rhs) => - val typer1 = typer.constrTyperIf(sym.hasFlag(PARAM | PRESUPER) && sym.owner.isConstructor) - if (tpt.isEmpty) { - if (rhs.isEmpty) { - context.error(tpt.pos, "missing parameter type"); - ErrorType - } else { - tpt.tpe = widenIfNotFinal( - sym, - newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType), - WildcardType) - tpt setPos vdef.pos - tpt.tpe - } - } else typer1.typedType(tpt).tpe - - case TypeDef(_, _, tparams, rhs) => - newNamer(context.makeNewScope(tree, sym)).typeDefSig(sym, tparams, rhs) //@M! - - case Import(expr, selectors) => - val expr1 = typer.typedQualifier(expr) - val base = expr1.tpe - typer.checkStable(expr1) - if (expr1.symbol.isRootPackage) context.error(tree.pos, "_root_ cannot be imported") - def checkNotRedundant(pos: Position, from: Name, to: Name): Boolean = { - if (!tree.symbol.hasFlag(SYNTHETIC) && - !((expr1.symbol ne null) && expr1.symbol.isInterpreterWrapper) && - base.member(from) != NoSymbol) { - val e = context.scope.lookupEntryWithContext(to)(context.owner) - def warnRedundant(sym: Symbol) = - context.unit.warning(pos, "imported `"+to+ - "' is permanently hidden by definition of "+sym+ - sym.locationString) - if ((e ne null) && e.owner == context.scope) { - warnRedundant(e.sym); return false - } else if (context eq context.enclClass) { - val defSym = context.prefix.member(to) filter ( - sym => sym.exists && context.isAccessible(sym, context.prefix, false)) - if (defSym != NoSymbol) { warnRedundant(defSym); return false } - } - } - true - } - def checkSelectors(selectors: List[(Name, Name)]): Unit = selectors match { - case (from, to) :: rest => - if (from != nme.WILDCARD && base != ErrorType) { - if (base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol) - context.error(tree.pos, from.decode + " is not a member of " + expr); - if (checkNotRedundant(tree.pos, from, to)) - checkNotRedundant(tree.pos, from.toTypeName, to.toTypeName) - } - if (from != nme.WILDCARD && (rest.exists (sel => sel._1 == from))) - context.error(tree.pos, from.decode + " is renamed twice"); - if ((to ne null) && to != nme.WILDCARD && (rest exists (sel => sel._2 == to))) - context.error(tree.pos, to.decode + " appears twice as a target of a renaming"); - checkSelectors(rest) - case Nil => - } - checkSelectors(selectors) - ImportType(expr1) - } - } catch { - case ex: TypeError => - //Console.println("caught " + ex + " in typeSig")//DEBUG - typer.reportTypeError(tree.pos, ex) - ErrorType - } - result match { - case PolyType(tparams, restpe) - if (!tparams.isEmpty && tparams.head.owner.isTerm || - // Adriaan: The added conditon below is quite a hack. It seems that HK type parameters is relying - // on a pass that forces all infos in the type to get everything right. - // The problem is that the same pass causes cyclic reference errors in - // test pos/cyclics.scala. It turned out that deSkolemize is run way more often than necessary, - // ruinning it only when needed fixes the cuclic reference errors. - // But correcting deSkolemize broke HK types, because we don't do the traversal anymore. - // For the moment I made a special hack to do the traversal if we have HK type parameters. - // Maybe it's not a hack, then we need to document it better. But ideally, we should find - // a way to deal with HK types that's not dependent on accidental side - // effects like this. - tparams.exists(!_.typeParams.isEmpty)) => - new DeSkolemizeMap(tparams) mapOver result - case _ => -// println("not skolemizing "+result+" in "+context.owner) -// new DeSkolemizeMap(List()) mapOver result - result - } - } - - /** Check that symbol's definition is well-formed. This means: - * - no conflicting modifiers - * - `abstract' modifier only for classes - * - `override' modifier never for classes - * - `def' modifier never for parameters of case classes - * - declarations only in mixins or abstract classes (when not @native) - */ - def validate(sym: Symbol) { - def checkNoConflict(flag1: Int, flag2: Int) { - if (sym.hasFlag(flag1) && sym.hasFlag(flag2)) - context.error(sym.pos, - if (flag1 == DEFERRED) - "abstract member may not have " + Flags.flagsToString(flag2) + " modifier"; - else - "illegal combination of modifiers: " + - Flags.flagsToString(flag1) + " and " + Flags.flagsToString(flag2) + - " for: " + sym + Flags.flagsToString(sym.rawflags)); - } - - if (sym.hasFlag(IMPLICIT) && !sym.isTerm) - context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods") - if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass && !inIDE) - context.error(sym.pos, "`implicit' modifier cannot be used for top-level objects") - if (sym.hasFlag(ABSTRACT) && !sym.isClass) - context.error(sym.pos, "`abstract' modifier can be used only for classes; " + - "\nit should be omitted for abstract members") - if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && !sym.hasFlag(TRAIT) && sym.isClass) - context.error(sym.pos, "`override' modifier not allowed for classes") - if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isConstructor) - context.error(sym.pos, "`override' modifier not allowed for constructors") - if (sym.hasFlag(ABSOVERRIDE) && !sym.owner.isTrait) - context.error(sym.pos, "`abstract override' modifier only allowed for members of traits") - if (sym.hasFlag(LAZY) && sym.hasFlag(PRESUPER)) - context.error(sym.pos, "`lazy' definitions may not be initialized early") - if (sym.info.typeSymbol == FunctionClass(0) && - 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 hasFlag DEFERRED) { // virtual classes count, too - if (sym.hasAttribute(definitions.NativeAttr)) - sym.resetFlag(DEFERRED) - else 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)) - sym.resetFlag(DEFERRED) - } - } - - checkNoConflict(DEFERRED, PRIVATE) - checkNoConflict(FINAL, SEALED) - checkNoConflict(PRIVATE, PROTECTED) - checkNoConflict(PRIVATE, OVERRIDE) - /* checkNoConflict(PRIVATE, FINAL) // can't do this because FINAL also means compile-time constant */ - checkNoConflict(DEFERRED, FINAL) - } - } - - abstract class TypeCompleter extends LazyType { - val tree: Tree - } - - def mkTypeCompleter(t: Tree)(c: Symbol => Unit) = new TypeCompleter { - val tree = t - override def complete(sym: Symbol) = c(sym) - } - - /** A class representing a lazy type with known type parameters. - */ - class PolyTypeCompleter(tparams: List[Tree], restp: TypeCompleter, owner: Tree, ownerSym: Symbol, ctx: Context) extends TypeCompleter { - override val typeParams: List[Symbol]= tparams map (_.symbol) //@M - override val tree = restp.tree - override def complete(sym: Symbol) { - if(ownerSym.isAbstractType) //@M an abstract type's type parameters are entered -- TODO: change to isTypeMember ? - newNamer(ctx.makeNewScope(owner, ownerSym)(PolyTypeCompleterScopeKind)).enterSyms(tparams) //@M - restp.complete(sym) - } - } - - /** The symbol that which this accessor represents (possibly in part). - * This is used for error messages, where we want to speak in terms - * of the actual declaration or definition, not in terms of the generated setters - * and getters */ - def underlying(member: Symbol): Symbol = - if (member hasFlag ACCESSOR) { - if (member.isDeferred) { - val getter = if (member.isSetter) member.getter(member.owner) else member - if (inIDE && getter == NoSymbol) return NoSymbol; - val result = getter.owner.newValue(getter.pos, getter.name) - .setInfo(getter.tpe.resultType) - .setFlag(DEFERRED) - if (getter.setter(member.owner) != NoSymbol) result.setFlag(MUTABLE) - result - } else member.accessed - } else member - - /** An explanatory note to be added to error messages - * when there's a problem with abstract var defs */ - def varNotice(sym: Symbol): String = - if (underlying(sym).isVariable) - "\n(Note that variables need to be initialized to be defined)" - else "" -} - |