diff options
author | Martin Odersky <odersky@gmail.com> | 2005-03-22 15:26:54 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-03-22 15:26:54 +0000 |
commit | 9e67e8eb2a4480d2761d2e08a87cea6b32a71fbb (patch) | |
tree | e71a2f25b3dd0072fa0db11c6e2e1282d4cfa97f /sources | |
parent | 7179a093ef8f5c46941f6440704389316416b7f5 (diff) | |
download | scala-9e67e8eb2a4480d2761d2e08a87cea6b32a71fbb.tar.gz scala-9e67e8eb2a4480d2761d2e08a87cea6b32a71fbb.tar.bz2 scala-9e67e8eb2a4480d2761d2e08a87cea6b32a71fbb.zip |
*** empty log message ***
Diffstat (limited to 'sources')
20 files changed, 571 insertions, 360 deletions
diff --git a/sources/scala/List.scala b/sources/scala/List.scala index 0563f49998..e4a109852d 100644 --- a/sources/scala/List.scala +++ b/sources/scala/List.scala @@ -748,7 +748,7 @@ sealed trait List[+a] extends Seq[a] { def flatMap[b](f: a => List[b]): List[b] = match { case Nil => Nil case head :: tail => f(head) ::: (tail flatMap f) - }; + } /** Reverses the elements of this list. * <p/> diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala index 36b250fbc3..aba47f7d89 100755 --- a/sources/scala/tools/nsc/Global.scala +++ b/sources/scala/tools/nsc/Global.scala @@ -11,7 +11,7 @@ import scala.tools.util._; import scala.collection.mutable.{HashSet,HashMap,ListBuffer} import symtab._; -import symtab.pickles.{PickleBuffer, Pickles}; +import symtab.classfile.{PickleBuffer, Pickler}; import util._; import ast._; import ast.parser._; @@ -38,7 +38,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable val global: Global.this.type = Global.this } - object pickles extends Pickles { + object pickler extends Pickler { val global: Global.this.type = Global.this } @@ -132,7 +132,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable } val namerPhase = new analyzer.NamerPhase(parserPhase); val typeCheckPhase = new analyzer.TypeCheckPhase(namerPhase); - val picklePhase = new pickles.PicklePhase(typeCheckPhase); + val picklePhase = new pickler.PicklePhase(typeCheckPhase); val terminalPhase = new StdPhase(picklePhase) { def name = "terminal"; diff --git a/sources/scala/tools/nsc/Phase.scala b/sources/scala/tools/nsc/Phase.scala index e4c8bf3f0e..1bb14483ac 100644 --- a/sources/scala/tools/nsc/Phase.scala +++ b/sources/scala/tools/nsc/Phase.scala @@ -5,8 +5,6 @@ // $Id$ package scala.tools.nsc; -import symtab.Flags.INITIALFLAGS; - abstract class Phase(val prev: Phase) { val id: int = if (prev == null) 0 else prev.id + 1; @@ -17,8 +15,6 @@ abstract class Phase(val prev: Phase) { def name: String; def description: String = name; - - val flagMask: long = if (prev == null) INITIALFLAGS else prev.flagMask; def exactMatch: boolean = false; def run: unit; diff --git a/sources/scala/tools/nsc/ast/TreeGen.scala b/sources/scala/tools/nsc/ast/TreeGen.scala index 523bf74b78..f152bb2f2e 100755 --- a/sources/scala/tools/nsc/ast/TreeGen.scala +++ b/sources/scala/tools/nsc/ast/TreeGen.scala @@ -6,14 +6,111 @@ package scala.tools.nsc.ast; import scala.tools.util.Position; +import symtab.Flags._; abstract class TreeGen { val global: Global; import global._; + import definitions._; + import posAssigner.atPos; - def mkGlobalRef(sym: Symbol): Tree = Ident(sym.name) setSymbol sym setType sym.tpe; + /** Builds a reference to value whose type is given stable prefix. + */ + def mkQualifier(stable: Type): Tree = stable match { + case NoPrefix => + EmptyTree + case ThisType(clazz) => + if (clazz.isRoot || clazz.isEmptyPackageClass) EmptyTree else This(clazz) + case SingleType(pre, sym) => + val qual = mkStableRef(pre, sym); + qual.tpe match { + case MethodType(params, _) => + assert(params.isEmpty, qual.tpe); + Apply(qual, List()); + case _ => + qual + } + } - def This(sym: Symbol): Tree = global.This(sym.name) setSymbol sym setType sym.thisType; + /** Builds a reference to given symbol with given stable prefix. */ + def mkRef(pre: Type, sym: Symbol): Tree = { + val qual = mkQualifier(pre); + if (qual == EmptyTree) Ident(sym) else Select(qual, sym) + } + + /** Builds a reference to given symbol. */ + def mkRef(sym: Symbol): Tree = mkRef(sym.owner.thisType, sym); + + /** Replacecs tree type with a stable type if possible */ + def stabilize(tree: Tree): Tree = tree match { + case Ident(_) => + if (tree.symbol.isStable) tree.setType(singleType(NoPrefix, tree.symbol)) + else tree + case Select(qual, _) => + if (tree.symbol.isStable && qual.tpe.isStable) tree.setType(singleType(qual.tpe, tree.symbol)) + else tree + case _ => + tree + } + + /** Builds a reference with stable type to given symbol */ + def mkStableRef(pre: Type, sym: Symbol): Tree = stabilize(mkRef(pre, sym)); + def mkStableRef(sym: Symbol): Tree = stabilize(mkRef(sym)); + + def TypeTree(tp: Type) = global.TypeTree() setType tp; + + def This(sym: Symbol) = + global.This(sym.name) setSymbol sym setType sym.thisType; + + def Ident(sym: Symbol) = { + assert(sym.isTerm); + sym.setFlag(ACCESSED); + global.Ident(sym.name) setSymbol sym setType sym.tpe; + } + + def Select(qual: Tree, sym: Symbol) = { + assert(sym.isTerm); + sym.setFlag(ACCESSED); + global.Select(qual, sym.name) setSymbol sym setType qual.tpe.memberType(sym); + } + + def Apply(fun: Tree, args: List[Tree]) = fun.tpe match { + case MethodType(formals, restpe) => + global.Apply(fun, args) setType restpe + } + + def Assign(lhs: Tree, rhs: Tree) = + global.Assign(lhs, rhs) setType UnitClass.tpe; + + def ValDef(sym: Symbol, rhs: Tree): ValDef = atPos(sym.pos) { + global.ValDef(flags2mods(sym.flags), sym.name, TypeTree(sym.tpe), rhs) + } + def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree); + + def AbsTypeDef(sym: Symbol) = + global.AbsTypeDef(flags2mods(sym.flags), sym.name, + TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi)); + + def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree) = atPos(sym.pos) { + var cnt = 0; + def freshName = { cnt = cnt + 1; newTermName("x$" + cnt) } + def mk(tparams: List[Symbol], vparamss: List[List[Symbol]], tpe: Type): DefDef = tpe match { + case PolyType(tparams, restpe) => + mk(tparams, List(), restpe) + case MethodType(formals, restpe) => + val vparams: List[Symbol] = formals map sym.newValueParameter(sym.pos, freshName).setInfo; + mk(tparams, vparamss ::: List(vparams), restpe) + case _ => + global.DefDef( + flags2mods(sym.flags), + sym.name, + tparams.map(AbsTypeDef), + vparamss.map(.map(ValDef)), + TypeTree(tpe), + rhs(vparamss)) + } + mk(List(), List(), sym.tpe) + } } diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala index 7e314683be..1a1f64a872 100644 --- a/sources/scala/tools/nsc/ast/Trees.scala +++ b/sources/scala/tools/nsc/ast/Trees.scala @@ -220,7 +220,7 @@ class Trees: Global { /** General type term, introduced by RefCheck. */ case class TypeTree() extends TypTree { - override def isEmpty = tpe == null; + override def isEmpty = tpe == null || tpe == NoType; } /** Singleton type, eliminated by RefCheck */ diff --git a/sources/scala/tools/nsc/ast/parser/Syntactic.scala b/sources/scala/tools/nsc/ast/parser/Syntactic.scala index ac369fa790..479e0a65d6 100755 --- a/sources/scala/tools/nsc/ast/parser/Syntactic.scala +++ b/sources/scala/tools/nsc/ast/parser/Syntactic.scala @@ -1283,15 +1283,15 @@ abstract class Syntactic: ParserPhase { false } - /** Def ::= val PatDef - * | var VarDef - * | def FunDef - * | type TypeDef + /** Def ::= val PatDef {`,' PatDef} + * | var VarDef {`,' VatDef} + * | def FunDef {`,' FunDef} + * | type TypeDef {`,' TypeDef} * | TmplDef - * Dcl ::= val ValDcl - * | var ValDcl - * | def FunDcl - * | type TypeDcl + * Dcl ::= val ValDcl {`,' ValDcl} + * | var ValDcl {`,' ValDcl} + * | def FunDcl {`,' FunDcl} + * | type TypeDcl {`,' TypeDcl} */ def defOrDcl(mods: int): List[Tree] = { in.token match { @@ -1300,12 +1300,12 @@ abstract class Syntactic: ParserPhase { case VAR => varDefOrDcl(mods); case DEF => - funDefOrDcl(mods); + List(funDefOrDcl(mods)); case TYPE => in.nextToken(); List(typeDefOrDcl(mods)) case _ => - tmplDef(mods) + List(tmplDef(mods)) } } @@ -1367,43 +1367,33 @@ abstract class Syntactic: ParserPhase { atPos(pos) { ValDef(newmods, name, tp.duplicate, rhs.duplicate) } } - /** FunDef ::= FunSig {`,' FunSig} `:' Type `=' Expr + /** FunDef ::= FunSig `:' Type `=' Expr * | this ParamClause `=' ConstrExpr - * FunDcl ::= FunSig {`,' FunSig} `:' Type + * FunDcl ::= FunSig `:' Type * FunSig ::= id [FunTypeParamClause] ParamClauses */ - def funDefOrDcl(mods: int): List[Tree] = { - in.nextToken(); - if (in.token == THIS) - List( - atPos(in.skipToken()) { - val vparams = List(paramClause(false)); - accept(EQUALS); - DefDef( - mods, nme.CONSTRUCTOR, List(), vparams, TypeTree(), constrExpr()) - }) - else { - var newmods = mods; - val lhs = new ListBuffer[Tuple4[Int, Name, List[AbsTypeDef], List[List[ValDef]]]] - + Tuple4( - in.pos, ident(), typeParamClauseOpt(false), paramClauses(false)); - while (in.token == COMMA) - lhs += Tuple4( - in.skipToken(), ident(), typeParamClauseOpt(false), paramClauses(false)); - val restype = typedOpt(); - val rhs = - if (restype == EmptyTree || in.token == EQUALS) equalsExpr(); - else { - newmods = newmods | Flags.DEFERRED; - EmptyTree - } - for (val Tuple4(pos, name, tparams, vparams) <- lhs.toList) yield - atPos(pos) { - DefDef(newmods, name, tparams, vparams, - restype.duplicate, rhs.duplicate) - } + def funDefOrDcl(mods: int): Tree = + atPos(in.skipToken()) { + if (in.token == THIS) { + in.nextToken(); + val vparams = List(paramClause(false)); + accept(EQUALS); + DefDef(mods, nme.CONSTRUCTOR, List(), vparams, TypeTree(), constrExpr()) + } else { + var newmods = mods; + val name = ident(); + val tparams = typeParamClauseOpt(false); + val vparamss = paramClauses(false); + val restype = typedOpt(); + val rhs = + if (restype == EmptyTree || in.token == EQUALS) equalsExpr(); + else { + newmods = newmods | Flags.DEFERRED; + EmptyTree + } + DefDef(newmods, name, tparams, vparamss, restype, rhs) + } } - } /** ConstrExpr ::= SelfInvocation * | `{' SelfInvocation {`;' BlockStat} `}' @@ -1452,9 +1442,9 @@ abstract class Syntactic: ParserPhase { /** TmplDef ::= ([case] class | trait) ClassDef * | [case] object ObjectDef */ - def tmplDef(mods: int): List[Tree] = in.token match { + def tmplDef(mods: int): Tree = in.token match { case TRAIT => - classDef(mods | Flags.TRAIT | Flags.ABSTRACT); + classDef(mods | Flags.ABSTRACT); case CLASS => classDef(mods); case CASECLASS => @@ -1465,48 +1455,36 @@ abstract class Syntactic: ParserPhase { objectDef(mods | Flags.CASE); case _ => syntaxError("illegal start of definition", true); - List() + EmptyTree } - /** ClassDef ::= ClassSig {`,' ClassSig} [`:' SimpleType] ClassTemplate + /** ClassDef ::= ClassSig [`:' SimpleType] ClassTemplate * ClassSig ::= Id [TypeParamClause] [ClassParamClause] */ - def classDef(mods: int): List[Tree] = { - val lhs = new ListBuffer[Tuple4[Int, Name, List[AbsTypeDef], List[List[ValDef]]]]; - do { - lhs += Tuple4(in.skipToken(), - ident().toTypeName, - typeParamClauseOpt(true), - if ((mods & Flags.TRAIT) != 0) List() else paramClauses(true)) - } while (in.token == COMMA); - val thistpe = simpleTypedOpt(); - val template = classTemplate(mods); - for (val Tuple4(pos, name, tparams, vparamss) <- lhs.toList) yield - atPos(pos) { - val template1 = if ((mods & Flags.TRAIT) != 0) template - else addConstructor(mods, vparamss, template); - ClassDef(mods, name, tparams, thistpe.duplicate, template1.duplicate.asInstanceOf[Template]) - } - } + def classDef(mods: int): Tree = + atPos(in.skipToken()) { + val name = ident().toTypeName; + val tparams = typeParamClauseOpt(true); + if ((mods & Flags.CASE) != 0 && in.token != LPAREN) accept(LPAREN); + val vparamss = paramClauses(true); + val thistpe = simpleTypedOpt(); + val mods1 = if (vparamss.isEmpty && (mods & ABSTRACT) != 0) mods | Flags.TRAIT else mods; + val template = classTemplate(mods1, vparamss); + ClassDef(mods1, name, tparams, thistpe, template) + } - /** ObjectDef ::= Id { , Id } ClassTemplate + /** ObjectDef ::= Id ClassTemplate */ - def objectDef(mods: int): List[Tree] = { - val lhs = new ListBuffer[Pair[Int, Name]]; - do { - lhs += Pair(in.skipToken(), ident()); - } while (in.token == COMMA); - val template = classTemplate(mods); - for (val Pair(pos, name) <- lhs.toList) yield - atPos(pos) { - val template1 = addConstructor(mods, List(), template); - ModuleDef(mods, name, template1.duplicate.asInstanceOf[Template]) - } - } + def objectDef(mods: int): Tree = + atPos(in.skipToken()) { + val name = ident(); + val template = classTemplate(mods, List()); + ModuleDef(mods, name, template) + } - /** ClassTemplate ::= [`extends' SimpleType [`(' [Exprs] `)']] {`with' SimpleType} [TemplateBody] + /** ClassTemplate ::= [`extends' TemplateParents] [TemplateBody] */ - def classTemplate(mods: int): Template = + def classTemplate(mods: int, vparamss: List[List[ValDef]]): Template = atPos(in.pos) { val parents = new ListBuffer[Tree]; var args: List[Tree] = List(); @@ -1514,14 +1492,13 @@ abstract class Syntactic: ParserPhase { in.nextToken(); parents += simpleType(); if (in.token == LPAREN) args = argumentExprs(); - } else { - parents += scalaAnyRefConstr + while (in.token == WITH) { + in.nextToken(); + parents += simpleType() + } } - parents += scalaScalaObjectConstr; + parents += scalaScalaObjectConstr; if ((mods & Flags.CASE)!= 0) parents += caseClassConstr; - while (in.token == WITH) { - in.nextToken(); parents += simpleType(); - } val ps = parents.toList; var body = if (in.token == LBRACE) { @@ -1531,7 +1508,8 @@ abstract class Syntactic: ParserPhase { syntaxError("`extends' or `{' expected", true); List() } - if ((mods & Flags.TRAIT) == 0) body = makeSuperCall(args) :: body; + if ((mods & Flags.TRAIT) == 0) + body = makeConstructorPart(mods, vparamss, args) ::: body; Template(ps, body) } @@ -1591,7 +1569,7 @@ abstract class Syntactic: ParserPhase { in.token == LBRACKET || isModifier) { stats ++ - joinAttributes(attributeClauses(), joinComment(tmplDef(modifiers()))) + joinAttributes(attributeClauses(), joinComment(List(tmplDef(modifiers())))) } else if (in.token != SEMI) { syntaxError("illegal start of class or object definition", true); } @@ -1696,7 +1674,7 @@ abstract class Syntactic: ParserPhase { stats += Literal(()).setPos(in.pos) } } else if (isLocalModifier) { - stats ++= tmplDef(localClassModifiers()); + stats += tmplDef(localClassModifiers()); accept(SEMI); if (in.token == RBRACE || in.token == CASE) { stats += Literal(()).setPos(in.pos) diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala index c3a3254cc9..c9561c5e30 100755 --- a/sources/scala/tools/nsc/symtab/Definitions.scala +++ b/sources/scala/tools/nsc/symtab/Definitions.scala @@ -133,7 +133,7 @@ abstract class Definitions: SymbolTable { } private def newMethod(owner: Symbol, name: Name): Symbol = { - val msym = owner.newMethod(Position.NOPOS, name); + val msym = owner.newMethod(Position.NOPOS, name.encode); owner.info.decls.enter(msym); msym } @@ -145,13 +145,15 @@ abstract class Definitions: SymbolTable { def init = { RootClass = NoSymbol.newClass(Position.NOPOS, nme.ROOT.toTypeName) - .setFlag(FINAL | PACKAGE | JAVA).setInfo(rootLoader); + .setFlag(FINAL | MODULE | PACKAGE | JAVA).setInfo(rootLoader); EmptyPackage = RootClass.newPackage(Position.NOPOS, nme.EMPTY_PACKAGE_NAME).setFlag(FINAL); EmptyPackageClass = EmptyPackage.moduleClass; EmptyPackageClass.setInfo(ClassInfoType(List(), new Scope(), EmptyPackageClass)); - EmptyPackage.setInfo(EmptyPackageClass.typeConstructor); + + + EmptyPackage.setInfo(EmptyPackageClass.tpe); RootClass.info.decls.enter(EmptyPackage); JavaPackage = getModule("java"); diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala index fcaae4e8cf..776adab42e 100644 --- a/sources/scala/tools/nsc/symtab/Flags.scala +++ b/sources/scala/tools/nsc/symtab/Flags.scala @@ -63,11 +63,12 @@ object Flags { val TRANS_FLAG = 0x800000000l; // transient flag guaranteed to be reset after each phase. val LIFTED = TRANS_FLAG; // transient flag for lambdalift val INCONSTRUCTOR = TRANS_FLAG; // transient flag for analyzer - val INITIALFLAGS = 0x777777777l; // masks val SOURCEFLAGS = 0x00077777; // these modifiers can be set in source programs. - val EXPLICITFLAGS = // these modifiers can be explcitly in source programs. + val GENFLAGS = // these modifiers can be in generated trees + SOURCEFLAGS | SYNTHETIC | STABLE | ACCESSOR | ACCESS_METHOD | PARAMACCESSOR | LABEL | BRIDGE; + val EXPLICITFLAGS = // these modifiers can be set explicitly in source programs. PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED | OVERRIDE | CASE; val ACCESSFLAGS = PRIVATE | PROTECTED; @@ -75,14 +76,11 @@ object Flags { val CONSTRFLAGS = JAVA; val PICKLEDFLAGS = 0x77777777 & ~LOCKED & ~INITIALIZED; - /** Flags already set by object creation and never set afterwards */ - val CREATIONFLAGS = ACCESSFLAGS | METHOD | MODULE | MUTABLE | PARAM | PACKAGE | - COVARIANT | CONTRAVARIANT | SYNTHETIC | STABLE | ACCESSOR | PARAMACCESSOR | LOCAL | - IS_ERROR | OVERLOADED | INCONSTRUCTOR; - /** Module flags inherited by their module-class */ val MODULE2CLASSFLAGS = ACCESSFLAGS | PACKAGE; + def flags2mods(flags: long): int = flags.asInstanceOf[int] & GENFLAGS; + def flagsToString(flags: long): String = List.range(0, 63) .map(i => flagToString(flags & (1L << i))) diff --git a/sources/scala/tools/nsc/symtab/Names.scala b/sources/scala/tools/nsc/symtab/Names.scala index d5a51fc66d..ed9aad85fd 100755 --- a/sources/scala/tools/nsc/symtab/Names.scala +++ b/sources/scala/tools/nsc/symtab/Names.scala @@ -254,8 +254,8 @@ class Names { val str = toString(); val res = NameTransformer.encode(str); if (res == str) this - else if (isTypeName) newTypeName(str) - else newTermName(str) + else if (isTypeName) newTypeName(res) + else newTermName(res) } /** Replace $op_name by corresponding operator symbol */ diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala index 52f09275fc..2c3603dbaa 100755 --- a/sources/scala/tools/nsc/symtab/StdNames.scala +++ b/sources/scala/tools/nsc/symtab/StdNames.scala @@ -25,6 +25,8 @@ abstract class StdNames: SymbolTable { def TUPLE_FIELD(index: int) = newTermName(TUPLE_FIELD_PREFIX_STRING + index); + def SETTER_NAME(name: Name) = encode(name.toString() + "_="); + val ERROR = newTermName("<error>"); val ERRORtype = newTypeName("<error>"); diff --git a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala index b441231bd4..7e69107d45 100755 --- a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -9,7 +9,7 @@ import java.io.IOException; import scala.tools.util.{AbstractFile, Position} import scala.tools.nsc.util.NameTransformer; import scala.collection.mutable.HashMap; -import classfile.ClassfileParser; +import classfile.{ClassfileParser, SymblfileParser}; import Flags._; @@ -80,12 +80,11 @@ abstract class SymbolLoaders { module.moduleClass.setInfo(errorLoader); owner.info.decls.enter(clazz); owner.info.decls.enter(module); - assert(clazz.linkedModule == module); + assert(clazz.linkedModule == module, "" + module + module.hasFlag(MODULE)); assert(module.linkedClass == clazz); } val sources = new HashMap[String, AbstractFile]; - val symbols = new HashMap[String, AbstractFile]; val classes = new HashMap[String, AbstractFile]; val packages = new HashMap[String, AbstractFile]; val it = directory.list(); @@ -96,8 +95,8 @@ abstract class SymbolLoaders { if (filename != "META_INF" && !packages.isDefinedAt(filename)) packages(filename) = file; } else if (filename.endsWith(".symbl")) { val name = filename.substring(0, filename.length() - 6); - if (!symbols.isDefinedAt(name) || - symbols(name).getName().endsWith(".class")) symbols(name) = file; + if (!classes.isDefinedAt(name) || + classes(name).getName().endsWith(".class")) classes(name) = file; } else if (filename.endsWith(".class")) { val name = filename.substring(0, filename.length() - 6); if (!classes.isDefinedAt(name)) classes(name) = file; @@ -115,7 +114,10 @@ abstract class SymbolLoaders { for (val Pair(name, cfile) <- classes.elements) { sources.get(name) match { case Some(sfile) if (sfile.lastModified() > cfile.lastModified()) => {} - case _ => enterClassAndModule(name, classfileLoader(cfile)); + case _ => + val loader = if (cfile.getName().endsWith(".symbl")) symblfileLoader(cfile) + else classfileLoader(cfile); + enterClassAndModule(name, loader) } } for (val Pair(name, file) <- packages.elements) { @@ -130,12 +132,22 @@ abstract class SymbolLoaders { val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global; } + private object symblfileParser extends SymblfileParser { + val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global; + } + def classfileLoader(file: AbstractFile) = new SymbolLoader(root => { classfileParser.parse(file, root); "class file '" + file + "'"; }); + def symblfileLoader(file: AbstractFile) = + new SymbolLoader(root => { + symblfileParser.parse(file, root); + "symbl file '" + file + "'"; + }); + def sourcefileLoader(file: AbstractFile) = new SymbolLoader(root => { global.compileLate(file); diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala index e7eeaa92c2..7d87f7e552 100755 --- a/sources/scala/tools/nsc/symtab/Symbols.scala +++ b/sources/scala/tools/nsc/symtab/Symbols.scala @@ -22,7 +22,7 @@ abstract class Symbols: SymbolTable { var name = initName; var pos = initPos; val id = { ids = ids + 1; ids } - var rawflags: long = 0; + private var rawflags: long = 0; // Creators ------------------------------------------------------------------- @@ -51,8 +51,9 @@ abstract class Symbols: SymbolTable { m.moduleClass.setFlag(JAVA | PACKAGE); m } - final def newThisSym(pos: int) = + final def newThisSym(pos: int) = { newValue(pos, nme.this_).setFlag(SYNTHETIC); + } final def newImport(pos: int) = newValue(pos, nme.IMPORT).setFlag(SYNTHETIC); final def newOverloaded(pre: Type, alternatives: List[Symbol]): Symbol = @@ -88,33 +89,33 @@ abstract class Symbols: SymbolTable { def isType = false; //to be overridden def isClass = false; //to be overridden - final def isValue = isTerm && !(isModule && ((rawflags & (PACKAGE | JAVA)) != 0)); - final def isVariable = isTerm && (rawflags & MUTABLE) != 0; - final def isGetter = isTerm && (rawflags & ACCESSOR) != 0 && !name.endsWith(nme._EQ); - final def isSetter = isTerm && (rawflags & ACCESSOR) != 0 && name.endsWith(nme._EQ); - final def isValueParameter = isTerm && (rawflags & PARAM) != 0; + final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA)); + final def isVariable = isTerm && hasFlag(MUTABLE); + final def isGetter = isTerm && hasFlag(ACCESSOR) && !name.endsWith(nme._EQ); + final def isSetter = isTerm && hasFlag(ACCESSOR) && name.endsWith(nme._EQ); + final def isValueParameter = isTerm && hasFlag(PARAM); final def isLocalDummy = isTerm && (name startsWith nme.LOCAL_PREFIX); - final def isMethod = isTerm && (rawflags & (METHOD | STABLE)) == METHOD; - final def isLabel = isTerm && (rawflags & LABEL) != 0; + final def isMethod = isTerm && (flags & (METHOD | STABLE)) == METHOD; + final def isLabel = isTerm && hasFlag(LABEL); final def isConstructor = isTerm && name == nme.CONSTRUCTOR; - final def isModule = isTerm && (rawflags & MODULE) != 0; - final def isPackage = isModule && (rawflags & PACKAGE) != 0; + final def isModule = isTerm && hasFlag(MODULE); + final def isPackage = isModule && hasFlag(PACKAGE); final def isThisSym = isTerm && name == nme.this_; - final def isError = (rawflags & IS_ERROR) != 0; - final def isAliasType = isType && !isClass && (rawflags & DEFERRED) == 0; - final def isAbstractType = isType && !isClass && (rawflags & DEFERRED) != 0; - final def isTypeParameter = isType && (rawflags & PARAM) != 0; + final def isError = hasFlag(IS_ERROR); + 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 isAnonymousClass = isClass && (name startsWith nme.ANON_CLASS_NAME); // startsWith necessary because name may grow when lifted final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME; // no lifting for refinement classes - final def isModuleClass = isClass && (rawflags & MODULE) != 0; - final def isPackageClass = isClass && (rawflags & PACKAGE) != 0; + final def isModuleClass = isClass && hasFlag(MODULE); + final def isPackageClass = isClass && hasFlag(PACKAGE); final def isRoot = isPackageClass && name == nme.ROOT.toTypeName; final def isEmptyPackageClass = isPackageClass && name == nme.EMPTY_PACKAGE_NAME.toTypeName; /** Does this symbol denote a stable value? */ final def isStable = - isTerm && (rawflags & MUTABLE) == 0 && - ((rawflags & METHOD) == 0 || (rawflags & STABLE) != 0); + isTerm && !hasFlag(MUTABLE) && (!hasFlag(METHOD) || hasFlag(STABLE)); /** Does this symbol denote the primary constructor * of its enclosing class? */ @@ -155,21 +156,18 @@ abstract class Symbols: SymbolTable { /** The variance of this symbol as an integer */ final def variance: int = - if ((rawflags & COVARIANT) != 0) 1 - else if ((rawflags & CONTRAVARIANT) != 0) -1 + if (hasFlag(COVARIANT)) 1 + else if (hasFlag(CONTRAVARIANT)) -1 else 0; // Flags ---------------------------------------------------------------------------- - final def flags = { - initialize; rawflags & phase.flagMask - } + final def flags = rawflags; + final def flags_=(fs: long) = rawflags = fs; final def setFlag(mask: long): this.type = { rawflags = rawflags | mask; this } final def resetFlag(mask: long): this.type = { rawflags = rawflags & ~mask; this } - final def getFlag(mask: long): long = - (if ((mask & ~CREATIONFLAGS) == 0) rawflags else flags) & mask; - final def hasFlag(mask: long): boolean = - ((if ((mask & ~CREATIONFLAGS) == 0) rawflags else flags) & mask) != 0; + final def getFlag(mask: long): long = rawflags & mask; + final def hasFlag(mask: long): boolean = (rawflags & mask) != 0; final def resetFlags: unit = { rawflags = rawflags & SOURCEFLAGS } // Info and Type ------------------------------------------------------------------- @@ -200,8 +198,8 @@ abstract class Symbols: SymbolTable { phase = infos.start; //System.out.println("completing " + this);//DEBUG tp.complete(this); - phase = current; rawflags = rawflags & ~LOCKED; + phase = current; cnt = cnt + 1; // allow for two completions: // one: sourceCompleter to LazyType, two: LazyType to completed type @@ -215,10 +213,10 @@ abstract class Symbols: SymbolTable { infos = new TypeHistory(phase, info, null); limit = phase; assert(info != null, "setInfo(null) for " + name + " at phase " + phase);//debug - rawflags = if (info.isComplete) rawflags | INITIALIZED - else rawflags & ~INITIALIZED; + rawflags = if (info.isComplete) rawflags | INITIALIZED & ~LOCKED; + else rawflags & ~INITIALIZED & ~LOCKED; if (info.isInstanceOf[MethodType] || info.isInstanceOf[PolyType]) - assert(isClass || (rawflags & METHOD) != 0); + assert(isClass || hasFlag(METHOD)); this } @@ -351,7 +349,7 @@ abstract class Symbols: SymbolTable { /** A clone of this symbol, but with given owner */ final def cloneSymbol(owner: Symbol): Symbol = - cloneSymbolImpl(owner).setInfo(info.cloneInfo(owner)).setFlag(rawflags); + cloneSymbolImpl(owner).setInfo(info.cloneInfo(owner)).setFlag(flags); /** Internal method to clone a symbol's implementation without flags or type */ @@ -390,7 +388,7 @@ abstract class Symbols: SymbolTable { /** The symbol accessed by this accessor function. */ final def accessed: Symbol = { - assert((rawflags & ACCESSOR) != 0); + assert(hasFlag(ACCESSOR)); val name1 = if (name.endsWith(nme._EQ)) name.subName(0, name.length - nme._EQ.length) else name; owner.info.decl(name1.toString() + "$") @@ -423,7 +421,7 @@ abstract class Symbols: SymbolTable { /** The module corresponding to this module class (note that this * is not updated when a module is cloned). */ - //def sourceModule: Symbol = NoSymbol; + def sourceModule: Symbol = NoSymbol; /** The module class corresponding to this module. */ @@ -450,10 +448,9 @@ abstract class Symbols: SymbolTable { /** String representation of symbol's definition key word */ final def keyString: String = - if (isClass) - if ((rawflags & TRAIT) != 0) - if ((rawflags & JAVA) != 0) "interface" else "trait" - else "class" + if (isTrait) + if (hasFlag(JAVA)) "interface" else "trait" + else if (isClass) "class" else if (isType && !hasFlag(PARAM)) "type" else if (isVariable) "var" else if (isPackage) "package" @@ -469,8 +466,8 @@ abstract class Symbols: SymbolTable { else if (isAnonymousClass) "<template>" else if (isRefinementClass) "" else if (isModuleClass) "singleton class" - else if (isClass) - if ((rawflags & TRAIT) != 0) "trait" else "class" + else if (isTrait) "trait" + else if (isClass) "class" else if (isType) "type" else if (isVariable) "variable" else if (isPackage) "package" @@ -557,7 +554,7 @@ abstract class Symbols: SymbolTable { /** String representation of symbol's definition */ final def defString: String = - compose(List(flagsToString(rawflags & EXPLICITFLAGS), + compose(List(flagsToString(flags & EXPLICITFLAGS), keyString, varianceString + nameString, infoString(rawInfo))); @@ -593,17 +590,27 @@ abstract class Symbols: SymbolTable { private var tpeCache: Type = _; private var valid: Phase = null; override def tpe: Type = { + assert(tpeCache != NoType, this); if (valid != phase) { valid = phase; - tpeCache = typeRef(owner.thisType, this, typeParams map (.tpe)); + tpeCache = NoType; + tpeCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, + this, typeParams map (.tpe)); } + assert(tpeCache != null, "" + this + " " + phase); tpeCache } override def typeConstructor: Type = { if (tyconCache == null) - tyconCache = typeRef(owner.thisType, this, List()); + tyconCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, + this, List()); tyconCache; } + override def setInfo(tp: Type): this.type = { + valid = null; + tyconCache = null; + super.setInfo(tp) + } override def reset(completer: Type): unit = { super.reset(completer); valid = null; @@ -624,8 +631,19 @@ abstract class Symbols: SymbolTable { thissym = this; } + private var thisTypeCache: Type = null; + /** the type this.type in this class */ - override val thisType: Type = ThisType(this); + override def thisType: Type = { + if (thisTypeCache == null) { + thisTypeCache = + if (isModuleClass && !isRoot) { + assert(sourceModule != NoSymbol); + singleType(owner.thisType, sourceModule); + } else ThisType(this); + } + thisTypeCache + } /** A symbol carrying the self type of the class as its type */ override def thisSym: Symbol = thissym; @@ -640,13 +658,16 @@ abstract class Symbols: SymbolTable { if (thisSym != this) clone.typeOfThis = typeOfThis; clone } + + override def sourceModule = if (isModuleClass) owner.linkedModule else NoSymbol; } - /** A class for module class symbols */ - class ModuleClassSymbol(module: ModuleSymbol) - extends ClassSymbol(module.owner, module.pos, module.name.toTypeName) { + /** A class for module class symbols + * Note: Not all module classes are of this type; when unpickled, we get plain class symbols! + */ + class ModuleClassSymbol(module: ModuleSymbol) extends ClassSymbol(module.owner, module.pos, module.name.toTypeName) { setFlag(module.getFlag(MODULE2CLASSFLAGS) | MODULE | FINAL); - //override def sourceModule = module; + override def sourceModule = module; } /** An object repreesenting a missing symbol */ diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala index 3dfc7651cd..a693da77a5 100755 --- a/sources/scala/tools/nsc/symtab/Types.scala +++ b/sources/scala/tools/nsc/symtab/Types.scala @@ -159,8 +159,10 @@ abstract class Types: SymbolTable { sym.info.asSeenFrom(this, sym.owner); /** The type of `sym', seen as a member of this type. */ - def memberType(sym: Symbol): Type = + def memberType(sym: Symbol): Type = { + assert(sym.tpe != null, sym);//debug sym.tpe.asSeenFrom(this, sym.owner); + } /** Substitute types `to' for occurrences of references to symbols `from' * in this type. */ @@ -291,7 +293,7 @@ abstract class Types: SymbolTable { var sym: Symbol = NoSymbol; var e: ScopeEntry = decls.lookupEntry(name); while (e != null) { - if ((e.sym.rawflags & excludedFlags) == 0) { + if (!e.sym.hasFlag(excludedFlags)) { if (sym == NoSymbol) sym = e.sym else { if (alts.isEmpty) alts = List(sym); @@ -315,11 +317,11 @@ abstract class Types: SymbolTable { var bcs = baseClasses; while (!bcs.isEmpty) { val decls = bcs.head.info.decls; - bcs = bcs.tail; + bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail; var entry = if (name == nme.ANYNAME) decls.elems else decls lookupEntry name; while (entry != null) { val sym = entry.sym; - val excl = sym.rawflags & excluded; + val excl = sym.getFlag(excluded); if (excl == 0) { if (name.isTypeName) { return sym @@ -407,6 +409,7 @@ abstract class Types: SymbolTable { /** A class for this-types of the form <sym>.this.type */ case class ThisType(sym: Symbol) extends SingletonType { + assert(!sym.isModuleClass || sym.isRoot, sym); override def symbol = sym; override def singleDeref: Type = sym.typeOfThis; override def prefixString = @@ -585,7 +588,13 @@ abstract class Types: SymbolTable { override def closure: Array[Type] = if (sym.isAbstractType) addClosure(this, transform(bounds.hi).closure) - else transform(sym.info.closure); + else { + val result = transform(sym.info.closure); + System.out.println("closure[" + this + "] = " + + List.fromArray(sym.info.closure) + " => " + result); + result + } + override def baseClasses: List[Symbol] = sym.info.baseClasses; @@ -691,7 +700,7 @@ abstract class Types: SymbolTable { private def rebind(pre: Type, sym: Symbol): Symbol = { val owner = sym.owner; if (owner.isClass && owner != pre.symbol && !sym.isFinal) { - val rebind = pre.nonPrivateMember(sym.name).suchThat(.isStable); + val rebind = pre.nonPrivateMember(sym.name).suchThat(sym => sym.isType || sym.isStable); if (rebind == NoSymbol) sym else rebind } else sym } @@ -988,9 +997,11 @@ abstract class Types: SymbolTable { case _ => mapOver(tp) } - private def register(sym: Symbol) = - if (result == NoSymbol || (result isNestedIn sym)) result = sym - else assert(result == sym || (sym isNestedIn result)); + private def register(sym: Symbol) = { + while (result != NoSymbol && sym != result && !(sym isNestedIn result)) + result = result.owner; + result + } } // Helper Methods ------------------------------------------------------------- @@ -998,21 +1009,22 @@ abstract class Types: SymbolTable { /** Do tp1 and tp2 denote equivalent types? */ def isSameType(tp1: Type, tp2: Type): boolean = (tp1 eq tp2) || { Pair(tp1, tp2) match { - case Pair(ErrorType, _) - | Pair(WildcardType, _) - | Pair(_, ErrorType) - | Pair(_, WildcardType) => - true - case Pair(NoType, _) - | Pair(NoPrefix, _) - | Pair(_, NoType) - | Pair(_, NoPrefix) => - false + case Pair(ErrorType, _) => true + case Pair(WildcardType, _) => true + case Pair(_, ErrorType) => true + case Pair(_, WildcardType) => true + + case Pair(NoType, _) => false + case Pair(NoPrefix, _) => false + case Pair(_, NoType) => false + case Pair(_, NoPrefix) => false + case Pair(ThisType(sym1), ThisType(sym2)) => sym1 == sym2 case Pair(SingleType(pre1, sym1), SingleType(pre2, sym2)) if (sym1 == sym2 && pre1 =:= pre2) => true + /* case Pair(SingleType(pre1, sym1), ThisType(sym2)) if (sym1.isModule && sym1.moduleClass == sym2 && @@ -1023,6 +1035,7 @@ abstract class Types: SymbolTable { sym2.moduleClass == sym1 && pre2 =:= sym1.owner.thisType) => true + */ case Pair(ConstantType(base1, value1), ConstantType(base2, value2)) => base1 =:= base2 && value1 == value2 case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) => @@ -1070,22 +1083,22 @@ abstract class Types: SymbolTable { /** Does tp1 conform to tp2? */ def isSubType(tp1: Type, tp2: Type): boolean = (tp1 eq tp2) || { Pair(tp1, tp2) match { - case Pair(ErrorType, _) - | Pair(WildcardType, _) - | Pair(_, ErrorType) - | Pair(_, WildcardType) => - true - case Pair(NoType, _) - | Pair(NoPrefix, _) - | Pair(_, NoType) - | Pair(_, NoPrefix) => - false - case Pair(ThisType(_), ThisType(_)) - | Pair(ThisType(_), SingleType(_, _)) - | Pair(SingleType(_, _), ThisType(_)) - | Pair(SingleType(_, _), SingleType(_, _)) - | Pair(ConstantType(_, _), ConstantType(_, _)) => - tp1 =:= tp2 + case Pair(ErrorType, _) => true + case Pair(WildcardType, _) => true + case Pair(_, ErrorType) => true + case Pair(_, WildcardType) => true + + case Pair(NoType, _) => false + case Pair(NoPrefix, _) => false + case Pair(_, NoType) => false + case Pair(_, NoPrefix) => false + + case Pair(ThisType(_), ThisType(_)) => tp1 =:= tp2 + case Pair(ThisType(_), SingleType(_, _)) => tp1 =:= tp2 + case Pair(SingleType(_, _), ThisType(_)) => tp1 =:= tp2 + case Pair(SingleType(_, _), SingleType(_, _)) => tp1 =:= tp2 + case Pair(ConstantType(_, _), ConstantType(_, _)) => tp1 =:= tp2 + case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) => def isSubArgs(tps1: List[Type], tps2: List[Type], tparams: List[Symbol]): boolean = { @@ -1105,9 +1118,7 @@ abstract class Types: SymbolTable { sym2.isAbstractType && (tp1 <:< tp2.bounds.lo) || sym2.isClass && - ({ val base = tp1 baseType sym2; - System.out.println("" + tp1 + " baseType " + sym2 + " = " + base); - !(base eq tp1) && (base <:< tp2) })//debug + ({ val base = tp1 baseType sym2; !(base eq tp1) && (base <:< tp2) })//debug || sym1 == AllClass || @@ -1193,6 +1204,7 @@ abstract class Types: SymbolTable { /** Prepend type `tp' to closure `cl' */ private def addClosure(tp: Type, cl: Array[Type]): Array[Type] = { val cl1 = new Array[Type](cl.length + 1); + assert(!tp.isInstanceOf[CompoundType], tp);//debug cl1(0) = tp; System.arraycopy(cl, 0, cl1, 1, cl.length); cl1 @@ -1446,6 +1458,7 @@ abstract class Types: SymbolTable { /** The most deeply nested owner that contains all the symbols * of thistype or prefixless typerefs/singletype occurrences in given list of types */ private def commonOwner(tps: List[Type]): Symbol = { + System.out.println("computing common owner of types " + tps);//debug commonOwnerMap.init; tps mapConserve commonOwnerMap; commonOwnerMap.result diff --git a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 38cebbe26c..8554452376 100755 --- a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -176,9 +176,12 @@ abstract class ClassfileParser { private def sigToType(name: Name): Type = { var index = 0; val end = name.length; + def objToAny(tp: Type): Type = + if (tp.symbol == definitions.ObjectClass) definitions.AnyClass.tpe + else tp; def paramsigs2types: List[Type] = if (name(index) == ')') { index = index + 1; List() } - else sig2type :: paramsigs2types; + else objToAny(sig2type) :: paramsigs2types; def sig2type: Type = { val tag = name(index); index = index + 1; tag match { @@ -240,6 +243,12 @@ abstract class ClassfileParser { for (val i <- Iterator.range(0, fieldCount)) parseField(); val methodCount = in.nextChar(); for (val i <- Iterator.range(0, methodCount)) parseMethod(); + if (instanceDefs.lookup(nme.CONSTRUCTOR) == NoSymbol && (sflags & INTERFACE) == 0) { + System.out.println("adding constructor to " + clazz);//debug + instanceDefs enter + clazz.newConstructor(Position.NOPOS) + .setFlag(clazz.flags & CONSTRFLAGS).setInfo(MethodType(List(), clazz.tpe)); + } } } diff --git a/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala b/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala index e123de3434..8bfd9709ad 100755 --- a/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala +++ b/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala @@ -146,9 +146,10 @@ abstract class MetaParser{ def parse(): Type = { nextToken(); if (token == "(") MethodType(parseParams(), parse()) - else definitions.UnitClass.tpe + else owner.owner.tpe } owner.setInfo(parse()); + System.out.println("constr " + owner + " = " + owner.info); assert(token == ";") } } diff --git a/sources/scala/tools/nsc/typechecker/Contexts.scala b/sources/scala/tools/nsc/typechecker/Contexts.scala index 65e8b0925d..afaa1542b3 100755 --- a/sources/scala/tools/nsc/typechecker/Contexts.scala +++ b/sources/scala/tools/nsc/typechecker/Contexts.scala @@ -21,8 +21,9 @@ class Contexts: Analyzer { definitions.RootClass, definitions.RootClass.info.decls); def addImport(pkg: Symbol): unit = { - val impTree = Import(gen.mkGlobalRef(pkg), List(Pair(nme.WILDCARD, null))) - setSymbol NoSymbol.newImport(Position.NOPOS).setInfo(pkg.tpe) + val qual = gen.mkStableRef(pkg); + val impTree = Import(qual, List(Pair(nme.WILDCARD, null))) + setSymbol NoSymbol.newImport(Position.NOPOS).setInfo(ImportType(qual)) setType NoType; sc = sc.make( Template(List(), List(impTree)) setSymbol NoSymbol setType NoType, sc.owner, sc.scope) @@ -123,7 +124,13 @@ class Contexts: Analyzer { } } - class ImportInfo(val tree: Import, val depth: int) { + class ImportInfo(tree: Import, val depth: int) { + + /** The prefix expression */ + def qual: Tree = tree.symbol.info match { + case ImportType(expr) => expr + case _ => throw new FatalError("symbol " + tree.symbol + " has bad type: " + tree.symbol.info);//debug + } /** Is name imported explicitly, not via wildcard? */ def isExplicitImport(name: Name): boolean = @@ -150,6 +157,8 @@ class Contexts: Analyzer { override def toString() = tree.toString(); } + + case class ImportType(expr: Tree) extends Type; } diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala index 693d1db576..7b1ac4f6cc 100755 --- a/sources/scala/tools/nsc/typechecker/Namers.scala +++ b/sources/scala/tools/nsc/typechecker/Namers.scala @@ -26,14 +26,14 @@ trait Namers: Analyzer { private def doubleDefError(pos: int, sym: Symbol): unit = context.unit.error(pos, sym.name.toString() + " is already defined as " + - (if ((sym.rawflags & CASE) != 0) "case class " + sym.name else sym.toString())); + (if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString())); private def updatePosFlags(sym: Symbol, pos: int, mods: int): Symbol = { if (settings.debug.value) System.out.println("overwriting " + sym); sym.pos = pos; - val oldflags = sym.rawflags & (INITIALIZED | LOCKED); + val oldflags = sym.flags & (INITIALIZED | LOCKED); val newflags = mods & ~(INITIALIZED | LOCKED); - sym.rawflags = oldflags | newflags; + sym.flags = oldflags | newflags; if (sym.isModule) updatePosFlags(sym.moduleClass, pos, (mods & MODULE2CLASSFLAGS) | MODULE | FINAL); sym @@ -54,7 +54,10 @@ trait Namers: Analyzer { if (p.isPackage && context.scope == p.owner.info.decls) { p.pos = pos; p.moduleClass.pos = pos; p } else { - enterInScope(context.owner.newPackage(pos, name)) + val pkg = context.owner.newPackage(pos, name); + pkg.moduleClass.setInfo(new PackageClassInfoType(new Scope(), pkg)); + pkg.setInfo(pkg.moduleClass.tpe); + enterInScope(pkg) } } @@ -94,14 +97,13 @@ trait Namers: Analyzer { def enterSym(tree: Tree): Symbol = { def finishWith(tparams: List[AbsTypeDef]) = { - if (settings.debug.value) log("entered " + tree.symbol); - val ltype = typer.typeCompleter(tree); - def makeParam(tparam: AbsTypeDef): Symbol = - tree.symbol.newTypeParameter(tparam.pos, tparam.name) - .setInfo(typer.typeCompleter(tparam)); - tree.symbol.setInfo( - if (tparams.isEmpty) ltype - else new LazyPolyType(tparams map makeParam, ltype)) + if (settings.debug.value) log("entered " + tree.symbol); + var ltype: LazyType = typer.typeCompleter(tree); + if (!tparams.isEmpty) { + new Namer(context.makeNewScope(tree, tree.symbol)).enterSyms(tparams); + ltype = new LazyPolyType(tparams map (.symbol), ltype); + } + tree.symbol.setInfo(ltype) } def finish = finishWith(List()); @@ -119,7 +121,7 @@ trait Namers: Analyzer { if ((mods & (CASE | ABSTRACT)) == CASE) { // enter case factory method. tree.symbol = enterCaseFactorySymbol( tree.pos, mods & ACCESSFLAGS | CASE, name.toTermName); - finishWith(tparams); + finishWith(tparams map (.duplicate.asInstanceOf[AbsTypeDef])); } tree.symbol = enterClassSymbol(tree.pos, mods, name); finishWith(tparams) @@ -135,7 +137,7 @@ trait Namers: Analyzer { .setFlag(accmods).setInfo(typer.getterTypeCompleter(tree)); enterInScope(getter); if ((mods & MUTABLE) != 0) { - val setter = owner.newMethod(tree.pos, name) + val setter = owner.newMethod(tree.pos, nme.SETTER_NAME(name)) .setFlag(accmods).setInfo(typer.setterTypeCompleter(tree)); enterInScope(setter) } @@ -152,16 +154,16 @@ trait Namers: Analyzer { } case DefDef(mods, nme.CONSTRUCTOR, tparams, vparams, tp, rhs) => tree.symbol = enterInScope(owner.newConstructor(tree.pos)) - .setFlag(mods | owner.rawflags & CONSTRFLAGS); + .setFlag(mods | owner.getFlag(CONSTRFLAGS)); finishWith(tparams) case DefDef(mods, name, tparams, _, _, _) => tree.symbol = enterInScope(owner.newMethod(tree.pos, name)).setFlag(mods); finishWith(tparams) case AbsTypeDef(mods, name, _, _) => - tree.symbol = enterInScope(owner.newAbstractType(tree.pos, name)); + tree.symbol = enterInScope(owner.newAbstractType(tree.pos, name)).setFlag(mods); finish case AliasTypeDef(mods, name, tparams, _) => - tree.symbol = enterInScope(owner.newAliasType(tree.pos, name)); + tree.symbol = enterInScope(owner.newAliasType(tree.pos, name)).setFlag(mods); finishWith(tparams) case Attributed(_, defn) => enterSym(defn) diff --git a/sources/scala/tools/nsc/typechecker/TypeCheckers.scala b/sources/scala/tools/nsc/typechecker/TypeCheckers.scala index a00b9829b1..3f9b4b41fa 100755 --- a/sources/scala/tools/nsc/typechecker/TypeCheckers.scala +++ b/sources/scala/tools/nsc/typechecker/TypeCheckers.scala @@ -51,6 +51,10 @@ trait TypeCheckers: Analyzer { // expressions may be packages and // Java statics modules. + private val TAPPmode = 0x080; // Set for the function/type constructor part + // of a type application. When set we do not + // decompose PolyTypes. + private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode | INCONSTRmode; /** Report a type error. @@ -81,11 +85,21 @@ trait TypeCheckers: Analyzer { /** Check that type of given tree does not contain local or private components */ - private object checkNoEscape extends TypeMap { + object checkNoEscaping extends TypeMap { private var owner: Symbol = _; + private var scope: Scope = _; private var badSymbol: Symbol = _; - def apply[T <: Tree](owner: Symbol, tree: T): T = { + + /** Check that type `tree' does not refer to private components unless itself is wrapped + * in something private (`owner' tells where the type occurs). */ + def privates[T <: Tree](owner: Symbol, tree: T): T = check(owner, EmptyScope, tree); + + /** Check that type `tree' does not refer to entities defined in scope `scope'. */ + def locals[T <: Tree](scope: Scope, tree: T): T = check(NoSymbol, scope, tree); + + def check[T <: Tree](owner: Symbol, scope: Scope, tree: T): T = { this.owner = owner; + this.scope = scope; badSymbol = NoSymbol; apply(tree.tpe); if (badSymbol == NoSymbol) tree @@ -98,21 +112,21 @@ trait TypeCheckers: Analyzer { } override def apply(t: Type): Type = { def checkNoEscape(sym: Symbol): unit = { - val e = context.scope.lookupEntry(sym.name); - if (e != null && e.sym == sym && e.owner == context.scope && !e.sym.isTypeParameter) { - badSymbol = e.sym - } else if (sym.hasFlag(PRIVATE)) { + if (sym.hasFlag(PRIVATE)) { var o = owner; while (o != NoSymbol && o != sym.owner && !o.isLocal && !o.hasFlag(PRIVATE)) o = o.owner; 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) badSymbol = e.sym } } if (badSymbol == NoSymbol) t match { - case TypeRef(NoPrefix, sym, args) => checkNoEscape(sym) - case SingleType(NoPrefix, sym) => checkNoEscape(sym) - case _ => + case TypeRef(_, sym, _) => checkNoEscape(sym) + case SingleType(_, sym) => checkNoEscape(sym) + case _ => } mapOver(t) } @@ -121,8 +135,8 @@ trait TypeCheckers: Analyzer { def reenterValueParams(vparamss: List[List[ValDef]]): unit = for (val vparams <- vparamss; val vparam <- vparams) context.scope enter vparam.symbol; - def reenterTypeParams(tparams: List[AbsTypeDef]): unit = - for (val tparam <- tparams) context.scope enter tparam.symbol; + def reenterTypeParams(tparams: List[AbsTypeDef]): List[Symbol] = + for (val tparam <- tparams) yield { context.scope enter tparam.symbol; tparam.symbol } def attrInfo(attr: Tree): AttrInfo = attr match { case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => @@ -151,7 +165,8 @@ trait TypeCheckers: Analyzer { * (1) Resolve overloading, unless mode contains FUNmode * (2) Apply parameterless functions * (3) Apply polymorphic types to fresh instances of their type parameters and - * store these instances in context.undetparams. + * store these instances in context.undetparams, + * unless followed by explicit type application. * (4) When in mode EXPRmode but not FUNmode, convert unapplied methods to functions * However, if function is `match' or a constructor, issue an error. * (5) Convert a class type that serves as a constructor in a pattern as follows: @@ -177,7 +192,7 @@ trait TypeCheckers: Analyzer { adapt(tree, mode, pt) case PolyType(List(), restpe) => // (2) transform(constfold(tree.setType(restpe)), mode, pt); - case PolyType(tparams, restpe) => // (3) + case PolyType(tparams, restpe) if ((mode & TAPPmode) == 0) => // (3) val tparams1 = tparams map (.cloneSymbol); val tree1 = if (tree.isType) tree else TypeApply(tree, tparams1 map (tparam => @@ -247,29 +262,34 @@ trait TypeCheckers: Analyzer { } def completeSuperType(supertpt: Tree, tparams: List[Symbol], vparamss: List[List[ValDef]], superargs: List[Tree]): Type = { - reenterValueParams(vparamss); + new Typer(context).enterValueParams(context.owner, vparamss); context.undetparams = tparams; transformExpr(atPos(supertpt.pos)(Apply(Select(New(supertpt), nme.CONSTRUCTOR), superargs))) .tpe } - def parentTypes(templ: Template): List[Tree] = - if (templ.parents.isEmpty) List() - else { - var supertpt = transform(templ.parents.head, TYPEmode | FUNmode, WildcardType); - val tparams = context.undetparams; - context.undetparams = List(); + def parentTypes(templ: Template): List[Tree] = { + var supertpt = transform(templ.parents.head, TYPEmode | FUNmode, WildcardType); + var mixins = templ.parents.tail map transformType; + if (supertpt.symbol != null) { + val tparams = supertpt.symbol.typeParams; if (!tparams.isEmpty) { val constr @ DefDef(_, _, _, vparamss, _, Apply(_, superargs)) = treeInfo.firstConstructor(templ.body); - supertpt = TypeTree() - setPos supertpt.pos - setType new TypeChecker(context.makeNewScope(constr, constr.symbol)) - .completeSuperType(supertpt, tparams, vparamss, superargs map (.duplicate)); + supertpt = gen.TypeTree( + new TypeChecker(context.makeNewScope(constr, context.owner.owner)) + .completeSuperType( + supertpt, + tparams, + vparamss map (.map(.duplicate.asInstanceOf[ValDef])), + superargs map (.duplicate))) setPos supertpt.pos; + } else if (supertpt.symbol.isTrait) { + supertpt = gen.TypeTree(supertpt.tpe.parents(0)) setPos supertpt.pos; + mixins = templ.parents } - checkNoEscape(context.owner, supertpt) :: - (templ.parents.tail mapConserve (tpt => transformType(tpt, context.owner))) } + (supertpt :: mixins) mapConserve (tpt => checkNoEscaping.privates(context.owner, tpt)) + } /** Check that * - all parents are class types, @@ -286,34 +306,36 @@ trait TypeCheckers: Analyzer { do { c = c.outer } while (c.owner == context.owner); val defscope = c.scope; - def validateParentClass(parent: Tree, isFirst: boolean): unit = { - val psym = parent.tpe.symbol; - if (!psym.isClass && !parent.tpe.isError) error(parent.pos, "class type expected"); - else if (isFirst == psym.hasFlag(TRAIT)) - error(parent.pos, "" + psym + - (if (isFirst) " is a trait; cannot be used as superclass" - else " is not a trait; cannot be used as mixin")) - else if (psym.hasFlag(FINAL)) - error(parent.pos, "illegal inheritance from final class"); - else if (psym.isSealed) { - // are we in same scope as base type definition? - val e = defscope.lookupEntry(psym.name); - if (!(e.sym == psym && e.owner == defscope)) { - // we are not within same statement sequence - var c = context; - while (c != NoContext && c.owner != psym) c = c.outer.enclClass; - if (c == NoContext) error(parent.pos, "illegal inheritance from sealed class") + def validateParentClass(parent: Tree, isFirst: boolean): unit = + if (!parent.tpe.isError) { + val psym = parent.tpe.symbol; + if (!psym.isClass) + error(parent.pos, "class type expected"); + else if (!isFirst && !psym.isTrait) + error(parent.pos, "" + psym + " is not a trait; cannot be used as mixin"); + else if (psym.hasFlag(FINAL)) + error(parent.pos, "illegal inheritance from final class"); + else if (psym.isSealed) { + // are we in same scope as base type definition? + val e = defscope.lookupEntry(psym.name); + if (!(e.sym == psym && e.owner == defscope)) { + // we are not within same statement sequence + var c = context; + while (c != NoContext && c.owner != psym) c = c.outer.enclClass; + if (c == NoContext) error(parent.pos, "illegal inheritance from sealed class") + } + } + if (!(selfType <:< parent.tpe.typeOfThis)) { + System.out.println(context.owner);//debug + System.out.println(context.owner.thisSym);//debug + error(parent.pos, "illegal inheritance;\n self-type " + + selfType + " does not conform to " + parent + + "'s selftype " + parent.tpe.typeOfThis); + if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis); } + if (parents exists (p => p != parent && p.tpe.symbol == psym && !psym.isError)) + error(parent.pos, "" + psym + " is inherited twice") } - if (!(selfType <:< parent.tpe.typeOfThis)) { - error(parent.pos, "illegal inheritance;\n self-type " + - selfType + " does not conform to " + parent + - "'s selftype " + parent.tpe.typeOfThis); - if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis); - } - if (parents exists (p => p != parent && p.tpe.symbol == psym && !psym.isError)) - error(parent.pos, "" + psym + " is inherited twice") - } if (!parents.isEmpty) { validateParentClass(parents.head, true); @@ -325,7 +347,7 @@ trait TypeCheckers: Analyzer { val clazz = cdef.symbol; reenterTypeParams(cdef.tparams); val tparams1 = cdef.tparams mapConserve transformAbsTypeDef; - val tpt1 = transformType(cdef.tpt, clazz.thisSym); + val tpt1 = checkNoEscaping.privates(clazz.thisSym, transformType(cdef.tpt)); val impl1 = new TypeChecker(context.make(cdef.impl, clazz, clazz.info.decls)) .transformTemplate(cdef.impl); copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, impl1) setType NoType @@ -338,17 +360,39 @@ trait TypeCheckers: Analyzer { copy.ModuleDef(mdef, mdef.mods, mdef.name, impl1) setType NoType } + def addGetterSetter(stat: Tree): List[Tree] = stat match { + case vd @ ValDef(mods, _, _, _) if (mods & PRIVATE) == 0 => + def setter: DefDef = { + val sym = vd.symbol; + val setter = sym.owner.info.decls.lookup(nme.SETTER_NAME(sym.name)).suchThat(.hasFlag(ACCESSOR)); + atPos(vd.pos)( + gen.DefDef(setter, vparamss => gen.Assign(gen.mkRef(vparamss.head.head), gen.mkRef(sym))) + ).setType(null) // to force type check + } + def getter: ValDef = { + val sym = vd.symbol; + val getter = sym.owner.info.decls.lookup(sym.name).suchThat(.hasFlag(ACCESSOR)); + atPos(vd.pos)( + gen.ValDef(getter, gen.mkRef(sym)) + ).setType(null) // to force type check + } + if ((mods & MUTABLE) != 0) List(stat, getter, setter) else List(stat, getter) + case _ => + List(stat) + } + def transformTemplate(templ: Template): Template = { templ setSymbol context.owner.newLocalDummy(templ.pos); val parents1 = parentTypes(templ); - validateParentClasses(parents1, context.owner.thisType); - val body1 = transformStats(templ.body, templ.symbol); - copy.Template(templ, parents1, body1) setType context.owner.tpe + validateParentClasses(parents1, context.owner.typeOfThis); + val body1 = templ.body flatMap addGetterSetter; + val body2 = transformStats(templ.body, templ.symbol); + copy.Template(templ, parents1, body2) setType context.owner.tpe } def transformValDef(vdef: ValDef): ValDef = { val sym = vdef.symbol; - val tpt1 = transformType(vdef.tpt, sym); + var tpt1 = checkNoEscaping.privates(sym, transformType(vdef.tpt)); val rhs1 = if (vdef.rhs.isEmpty) vdef.rhs else new TypeChecker(context.make(vdef, sym)).transform(vdef.rhs, EXPRmode, tpt1.tpe); @@ -361,7 +405,7 @@ trait TypeCheckers: Analyzer { reenterValueParams(ddef.vparamss); val tparams1 = ddef.tparams mapConserve transformAbsTypeDef; val vparamss1 = ddef.vparamss mapConserve (.mapConserve(transformValDef)); - val tpt1 = transformType(ddef.tpt, meth); + var tpt1 = checkNoEscaping.privates(meth, transformType(ddef.tpt)); val rhs1 = if (ddef.name == nme.CONSTRUCTOR) { if (!meth.hasFlag(SYNTHETIC) && @@ -381,15 +425,15 @@ trait TypeCheckers: Analyzer { } def transformAbsTypeDef(tdef: AbsTypeDef): AbsTypeDef = { - val lo1 = transformType(tdef.lo, tdef.symbol); - val hi1 = transformType(tdef.hi, tdef.symbol); + val lo1 = checkNoEscaping.privates(tdef.symbol, transformType(tdef.lo)); + val hi1 = checkNoEscaping.privates(tdef.symbol, transformType(tdef.hi)); copy.AbsTypeDef(tdef, tdef.mods, tdef.name, lo1, hi1) setType NoType } def transformAliasTypeDef(tdef: AliasTypeDef): AliasTypeDef = { reenterTypeParams(tdef.tparams); val tparams1 = tdef.tparams mapConserve transformAbsTypeDef; - val rhs1 = transformType(tdef.rhs, tdef.symbol); + val rhs1 = checkNoEscaping.privates(tdef.symbol, transformType(tdef.rhs)); copy.AliasTypeDef(tdef, tdef.mods, tdef.name, tparams1, rhs1) setType NoType } @@ -411,7 +455,8 @@ trait TypeCheckers: Analyzer { block.stats mapConserve transformExpr } val expr1 = transform(block.expr, mode & ~(FUNmode | QUALmode), pt); - checkNoEscape(NoSymbol, copy.Block(block, stats1, expr1) setType expr1.tpe.deconst) + checkNoEscaping.locals( + context.scope, copy.Block(block, stats1, expr1) setType expr1.tpe.deconst) } def transformCase(cdef: CaseDef, pattpe: Type, pt: Type): CaseDef = { @@ -444,7 +489,7 @@ trait TypeCheckers: Analyzer { val vparams1 = fun.vparams mapConserve transformValDef; val body1 = transform(fun.body, EXPRmode, respt); copy.Function(fun, vparams1, body1) - setType typeRef(clazz.info.prefix, clazz, (vparamSyms map (.tpe)) ::: List(body1.tpe)) + setType typeRef(clazz.tpe.prefix, clazz, (vparamSyms map (.tpe)) ::: List(body1.tpe)) } def transformRefinement(stats: List[Tree]): List[Tree] = { @@ -469,20 +514,23 @@ trait TypeCheckers: Analyzer { cases mapConserve (cdef => tc1.transformCase(cdef, pattp, pt)) } - def transformTypeApply(fun: Tree, args: List[Tree]): Tree = - if (fun.hasSymbol && fun.symbol.hasFlag(OVERLOADED)) { - transformTypeApply( - adapt(inferPolyAlternative(fun, args.length), funmode, WildcardType)) - } else { - val tparams = context.undetparams; - context.undetparams = List(); + def transformTypeApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match { + case OverloadedType(pre, alts) => + inferPolyAlternative(fun, args.length); + transformTypeApply(fun, args) + case PolyType(tparams, restpe) if (tparams.length != 0) => if (tparams.length == args.length) { - new TreeSubstituter(tparams, targs).traverse(fun); fun - } else if (tparams.length == 0) { - errorTree(tree, treeSymTypeMsg(tree, args) + " takes type parameters."); + val targs = args map (.tpe); + checkBounds(tree.pos, tparams, targs, ""); + System.out.println("type app " + tparams + " => " + targs + " = " + restpe.subst(tparams, targs));//debug + copy.TypeApply(tree, fun, args) setType restpe.subst(tparams, targs); } else { errorTree(tree, "wrong number of type parameters for " + treeSymTypeMsg(fun)) } + case ErrorType => + setError(tree) + case _ => + errorTree(tree, treeSymTypeMsg(fun) + " takes type parameters."); } def transformApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match { @@ -564,7 +612,10 @@ trait TypeCheckers: Analyzer { if (vmeth != NoSymbol) return transform(Select(Apply(Ident(vmeth.name), List(qual)), name), mode, pt) } - stabilize(checkAccessible(tree, sym, qual.tpe, qual), qual.tpe) + if (sym.info == NoType) + errorTree(tree, decode(name) + " is not a member of " + qual.tpe.widen) + else + stabilize(checkAccessible(tree, sym, qual.tpe, qual), qual.tpe) } /** Attribute an identifier consisting of a simple name or an outer reference. @@ -606,15 +657,17 @@ trait TypeCheckers: Analyzer { // update `pre' to be `sym's prefix type in case it is an imported member, // and compute value of: var qual: Tree = EmptyTree; // the qualififier tree if transformed tree is a select - if (defSym != NoSymbol) { - if (impSym != NoSymbol) + if (defSym.tpe != NoType) { + if (impSym.tpe != NoType) ambiguousError( "it is both defined in " + defSym.owner + " and imported subsequently by \n" + imports.head); - else if (defSym.owner.isClass && !defSym.owner.isPackageClass) - qual = gen.This(pre.symbol) setPos tree.pos; + else if (defSym.owner.isClass && !defSym.owner.isPackageClass && !defSym.isTypeParameter) + qual = gen.This(pre.symbol) setPos tree.pos + else + pre = NoPrefix; } else { - if (impSym != NoSymbol) { + if (impSym.tpe != NoType) { var impSym1 = NoSymbol; var imports1 = imports.tail; def ambiguousImportError = ambiguousError( @@ -632,14 +685,15 @@ trait TypeCheckers: Analyzer { } if (impSym1 != NoSymbol) ambiguousImportError; defSym = impSym; - qual = imports.head.tree.expr; + qual = imports.head.qual; pre = qual.tpe; } else { error(tree.pos, "not found: " + decode(name)); defSym = context.owner.newErrorSymbol(name); } } - stabilize(checkAccessible(tree, defSym, pre, qual), pre); + val tree1 = if (qual == EmptyTree) tree else Select(qual, name) setPos tree.pos; + stabilize(checkAccessible(tree1, defSym, pre, qual), pre); } /** Post-process an identifier or selection node, performing the following: @@ -747,15 +801,17 @@ trait TypeCheckers: Analyzer { } val lhs1 = transformExpr(lhs); val varsym = lhs1.symbol; + System.out.println("" + lhs1 + " " + " " + lhs1.getClass() + varsym);//debug if (varsym != null && isGetter(varsym)) { lhs1 match { case Select(qual, name) => - transform(Apply(Select(qual, name.toString() + "_="), List(rhs)), mode, pt) + transform(Apply(Select(qual, nme.SETTER_NAME(name)), List(rhs)), mode, pt) } } else if (varsym != null && varsym.isVariable) { val rhs1 = transform(rhs, EXPRmode, lhs.tpe); copy.Assign(tree, lhs1, rhs1) setType UnitClass.tpe; } else { + System.out.println("" + lhs1 + " " + " " + lhs1.getClass() + varsym);//debug if (!lhs.tpe.isError) error(tree.pos, "assignment to non-variable "); setError(tree) } @@ -780,7 +836,7 @@ trait TypeCheckers: Analyzer { val enclFun = context.owner.enclMethod; if (!enclFun.isMethod || enclFun.isConstructor) errorTree(tree, "return outside method definition") - else if ((context.owner.rawflags & INITIALIZED) == 0) + else if (context.owner.hasFlag(INITIALIZED)) errorTree(tree, "method with return needs result type") else { val expr1: Tree = transform(expr, EXPRmode, enclFun.tpe.resultType); @@ -800,8 +856,14 @@ trait TypeCheckers: Analyzer { copy.Throw(tree, expr1) setType AllClass.tpe case New(tpt: Tree) => - val tpt1 = transform(tpt, TYPEmode | FUNmode, WildcardType); - copy.New(tree, tpt1).setType(tpt.tpe) + var tpt1 = transform(tpt, TYPEmode | FUNmode, WildcardType); + if (tpt1.symbol != null && !tpt1.symbol.typeParams.isEmpty) { + context.undetparams = tpt1.symbol.typeParams; + tpt1 = TypeTree() + setPos tpt1.pos + setType appliedType(tpt1.tpe, context.undetparams map (.tpe)); + } + copy.New(tree, tpt1).setType(tpt1.tpe) case Typed(expr, tpt @ Ident(nme.WILDCARD_STAR)) => val expr1 = transform(expr, mode & stickyModes, seqType(pt)); @@ -812,12 +874,14 @@ trait TypeCheckers: Analyzer { setError(tree) } case Typed(expr, tpt) => - val tpt1 = transform(tpt, TYPEmode, WildcardType); + val tpt1 = transformType(tpt); val expr1 = transform(expr, mode & stickyModes, tpt1.tpe); - copy.Typed(tree, expr1, tpt1) + copy.Typed(tree, expr1, tpt1) setType tpt1.tpe case TypeApply(fun, args) => - transformTypeApply(transform(fun, funmode, WildcardType), args) + val args1 = args mapConserve transformType; + // do args first in order to maintain conext.undetparams on the function side. + transformTypeApply(transform(fun, funmode | TAPPmode, WildcardType), args1) case Apply(fun, args) => val funpt = if ((mode & PATTERNmode) != 0) pt else WildcardType; @@ -826,7 +890,7 @@ trait TypeCheckers: Analyzer { // number of arguments and expected result type. if (fun1.hasSymbol && fun1.symbol.hasFlag(OVERLOADED)) { val argtypes = args map (arg => AllClass.tpe); - val pre = fun1.symbol.info.prefix; + val pre = fun1.symbol.tpe.prefix; val sym = fun1.symbol filter (alt => isApplicable(context.undetparams, pre.memberType(alt), argtypes, pt)); if (sym != NoSymbol) @@ -843,7 +907,8 @@ trait TypeCheckers: Analyzer { else { val ps = clazz.info.parents dropWhile (p => p.symbol.name != mix); if (ps.isEmpty) { - error(tree.pos, "" + mix + " does not name a mixin base class of " + clazz); + System.out.println(clazz.info.parents map (.symbol.name));//debug + error(tree.pos, "" + mix + " does not name a base class of " + clazz); ErrorType } else ps.head } @@ -859,6 +924,15 @@ trait TypeCheckers: Analyzer { tree setSymbol clazz setType owntype } + case Select(qual @ Super(_, _), nme.CONSTRUCTOR) => + val qual1 = transform(qual, EXPRmode | QUALmode | POLYmode, WildcardType); + // the qualifier type of a supercall constructor is its first parent class + qual1.tpe match { + case RefinedType(parents, _) => qual1.tpe = parents.head; + case _ => + } + transformSelect(qual1, nme.CONSTRUCTOR); + case Select(qual, name) => var qual1 = transform(qual, EXPRmode | QUALmode | POLYmode, WildcardType); if (name.isTypeName) qual1 = checkStable(qual1); @@ -875,12 +949,11 @@ trait TypeCheckers: Analyzer { tree setType ref1.tpe.resultType; case SelectFromTypeTree(qual, selector) => - tree setType transformSelect(transform(qual, TYPEmode, WildcardType), selector).tpe + tree setType transformSelect(transformType(qual), selector).tpe case CompoundTypeTree(templ: Template) => tree setType { - val parents1 = templ.parents mapConserve (parent => - transform(parent, TYPEmode, WildcardType)); + val parents1 = templ.parents mapConserve transformType; if (parents1 exists (.tpe.isError)) ErrorType else { val decls = new Scope(); @@ -891,9 +964,9 @@ trait TypeCheckers: Analyzer { } case AppliedTypeTree(tpt, args) => - val tpt1 = transform(tpt, mode | FUNmode, WildcardType); - val tparams = tpt.tpe.symbol.typeParams; - val args1 = args mapConserve (arg => transform(arg, TYPEmode, WildcardType)); + val tpt1 = transform(tpt, mode | FUNmode | TAPPmode, WildcardType); + val tparams = tpt1.tpe.symbol.typeParams; + val args1 = args mapConserve transformType; if (tpt1.tpe.isError) setError(tree) else if (tparams.length == args1.length) @@ -919,14 +992,9 @@ trait TypeCheckers: Analyzer { setError(tree) } - def transformExpr(tree: Tree): Tree = - transform(tree, EXPRmode, WildcardType); - - def transformQualExpr(tree: Tree): Tree = - transform(tree, EXPRmode | QUALmode, WildcardType); - - def transformType(tree: Tree, owner: Symbol) = - checkNoEscape(owner, transform(tree, TYPEmode, WildcardType)); + def transformExpr(tree: Tree): Tree = transform(tree, EXPRmode, WildcardType); + def transformQualExpr(tree: Tree): Tree = transform(tree, EXPRmode | QUALmode, WildcardType); + def transformType(tree: Tree) = transform(tree, TYPEmode, WildcardType); } } diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala index e600c86625..441d6ab1e5 100755 --- a/sources/scala/tools/nsc/typechecker/Typers.scala +++ b/sources/scala/tools/nsc/typechecker/Typers.scala @@ -49,21 +49,14 @@ trait Typers: Analyzer { def selfTypeCompleter(tree: Tree) = new TypeCompleter(tree) { override def complete(sym: Symbol): unit = { - sym.setInfo(typechecker.transformType(tree, sym).tpe); + sym.setInfo(typechecker.transformType(tree).tpe); } } private def deconstIfNotFinal(sym: Symbol, tpe: Type): Type = - if (sym.isVariable || (sym.rawflags & FINAL) == 0) tpe.deconst else tpe; + if (sym.isVariable || sym.hasFlag(FINAL)) tpe.deconst else tpe; - - private def enterTypeParams(owner: Symbol, tparams: List[AbsTypeDef]): List[Symbol] = { - List.map2(owner.typeParams, tparams) - { (tpsym, tptree) => tptree.symbol = tpsym; context.scope enter tpsym; tpsym } - } - - private def enterValueParams(owner: Symbol, - vparamss: List[List[ValDef]]): List[List[Symbol]] = { + def enterValueParams(owner: Symbol, vparamss: List[List[ValDef]]): List[List[Symbol]] = { def enterValueParam(param: ValDef): Symbol = { param.symbol = owner.newValueParameter(param.pos, param.name) .setInfo(typeCompleter(param)); @@ -87,27 +80,26 @@ trait Typers: Analyzer { val parents = typechecker.parentTypes(templ) map (.tpe); val decls = new Scope(); new Namer(context.make(templ, clazz, decls)).enterSyms(templ.body); - ClassInfoType(parents, decls, clazz) - } + ClassInfoType(parents, decls, clazz) } private def classSig(tparams: List[AbsTypeDef], tpt: Tree, impl: Template): Type = { - val clazz = context.owner; - val tparamSyms = enterTypeParams(clazz, tparams); - if (!tpt.isEmpty) clazz.typeOfThis = selfTypeCompleter(tpt); + val tparamSyms = typechecker.reenterTypeParams(tparams); + if (!tpt.isEmpty) + context.owner.typeOfThis = selfTypeCompleter(tpt); else tpt.tpe = NoType; makePolyType(tparamSyms, templateSig(impl)) } private def methodSig(tparams: List[AbsTypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): Type = { val meth = context.owner; - val tparamSyms = enterTypeParams(meth, tparams); + val tparamSyms = typechecker.reenterTypeParams(tparams); val vparamSymss = enterValueParams(meth, vparamss); val restype = deconstIfNotFinal(meth, if (tpt.isEmpty) { tpt.tpe = if (meth.name == nme.CONSTRUCTOR) context.enclClass.owner.tpe else typechecker.transformExpr(rhs).tpe; tpt.tpe - } else typechecker.transformType(tpt, meth).tpe); + } else typechecker.transformType(tpt).tpe); def mkMethodType(vparams: List[Symbol], restpe: Type) = MethodType(vparams map (.tpe), restpe); makePolyType( @@ -117,7 +109,7 @@ trait Typers: Analyzer { } private def aliasTypeSig(tpsym: Symbol, tparams: List[AbsTypeDef], rhs: Tree): Type = - makePolyType(enterTypeParams(tpsym, tparams), typechecker.transformType(rhs, tpsym).tpe); + makePolyType(typechecker.reenterTypeParams(tparams), typechecker.transformType(rhs).tpe); private def typeSig(tree: Tree): Type = try { @@ -129,7 +121,7 @@ trait Typers: Analyzer { case ModuleDef(_, _, impl) => val clazz = sym.moduleClass; clazz.setInfo(new Typer(context.make(tree, clazz)).templateSig(impl)); - clazz.tpe + clazz.tpe; case DefDef(_, _, tparams, vparamss, tpt, rhs) => new Typer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs) @@ -145,14 +137,13 @@ trait Typers: Analyzer { .transformExpr(rhs).tpe; tpt.tpe } - else typechecker.transformType(tpt, sym).tpe) + else typechecker.transformType(tpt).tpe) case AliasTypeDef(_, _, tparams, rhs) => new Typer(context.makeNewScope(tree, sym)).aliasTypeSig(sym, tparams, rhs) case AbsTypeDef(_, _, lo, hi) => - TypeBounds(typechecker.transformType(lo, sym).tpe, - typechecker.transformType(hi, sym).tpe); + TypeBounds(typechecker.transformType(lo).tpe, typechecker.transformType(hi).tpe); case Import(expr, selectors) => val expr1 = typechecker.transformQualExpr(expr); @@ -168,7 +159,7 @@ trait Typers: Analyzer { checkSelectors(rest) case Nil => } - expr1.tpe + ImportType(expr1) } } catch { case ex: TypeError => diff --git a/sources/scala/tools/scalac/typechecker/RefCheck.scala b/sources/scala/tools/scalac/typechecker/RefCheck.scala index 99e3ed2b75..25eab9e202 100755 --- a/sources/scala/tools/scalac/typechecker/RefCheck.scala +++ b/sources/scala/tools/scalac/typechecker/RefCheck.scala @@ -978,18 +978,30 @@ class RefCheck(globl: scalac.Global) extends Transformer(globl) { // Tree node simplification--------------------------------------------------- - private def elimTypeNode(tree: Tree): Tree = + private def elimTypeNode(tree: Tree): Tree = { + def checkLegal(tp: Type): unit = tp match { + case Type.TypeRef(pre, sym, args) => + sym.kind match { + case ALIAS | TYPE => + checkLegal(sym.info().asSeenFrom(pre, sym.owner())); + case CLASS => + if (sym == defs.ANY_CLASS) + unit.error(tree.pos, "Array[Any] not supported"); + else if (sym == defs.ANYVAL_CLASS) + unit.error(tree.pos, "Array[AnyVal] not supported"); + case _ => + } + case _ => + } if (tree.isType()) { val resultType = tree.getType().deconst(); val resultArgs = resultType.typeArgs(); - if (resultType.symbol() == defs.ARRAY_CLASS && resultArgs.length == 1) { - if (resultArgs(0).symbol() == defs.ANY_CLASS) - unit.error(tree.pos, "Array[Any] not supported"); - else if (resultArgs(0).symbol() == defs.ANYVAL_CLASS) - unit.error(tree.pos, "Array[AnyVal] not supported"); + if (resultType.symbol() == defs.ARRAY_CLASS && resultArgs.length == 1 && global.runTimeTypes) { + checkLegal(resultArgs(0)) } gen.mkType(tree.pos, resultType); - } else tree; + } else tree + } // Transformation ------------------------------------------------------------ |