summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-05-17 15:39:54 +0000
committerMartin Odersky <odersky@gmail.com>2005-05-17 15:39:54 +0000
commit860077ec57d0ca5412c4448203e5028f3a783193 (patch)
tree216ee6f7f681247e34d8160c40c32b9c1d18ab69
parentea94e149516fcf20b1478f17b8c7d4fd6390f8ac (diff)
downloadscala-860077ec57d0ca5412c4448203e5028f3a783193.tar.gz
scala-860077ec57d0ca5412c4448203e5028f3a783193.tar.bz2
scala-860077ec57d0ca5412c4448203e5028f3a783193.zip
*** empty log message ***
-rwxr-xr-xsources/scala/tools/nsc/Global.scala3
-rwxr-xr-xsources/scala/tools/nsc/ast/TreeGen.scala22
-rw-r--r--sources/scala/tools/nsc/ast/TreeInfo.scala12
-rw-r--r--sources/scala/tools/nsc/ast/TreePrinters.scala3
-rw-r--r--sources/scala/tools/nsc/ast/Trees.scala32
-rwxr-xr-xsources/scala/tools/nsc/ast/parser/Parsers.scala30
-rwxr-xr-xsources/scala/tools/nsc/symtab/StdNames.scala1
-rwxr-xr-xsources/scala/tools/nsc/symtab/Types.scala45
-rw-r--r--sources/scala/tools/nsc/symtab/classfile/Pickle.scala11
-rwxr-xr-xsources/scala/tools/nsc/typechecker/ConstantFolder.scala43
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Contexts.scala4
-rw-r--r--sources/scala/tools/nsc/typechecker/EtaExpansion.scala12
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Infer.scala141
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Namers.scala14
-rw-r--r--sources/scala/tools/nsc/typechecker/TreeCheckers.scala60
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala322
16 files changed, 409 insertions, 346 deletions
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala
index 318f34b9b0..ca5c913c23 100755
--- a/sources/scala/tools/nsc/Global.scala
+++ b/sources/scala/tools/nsc/Global.scala
@@ -42,6 +42,8 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
val global: Global.this.type = Global.this
}
+ object typer extends analyzer.Typer(analyzer.NoContext);
+
object checker extends TreeCheckers {
val global: Global.this.type = Global.this
}
@@ -53,7 +55,6 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
// reporting -------------------------------------------------------
-
def error(msg: String) = reporter.error(null, msg);
def warning(msg: String) = reporter.warning(null, msg);
private def inform(msg: String) = reporter.info(null, msg, true);
diff --git a/sources/scala/tools/nsc/ast/TreeGen.scala b/sources/scala/tools/nsc/ast/TreeGen.scala
index 82190a13ce..d0b1d6a2f6 100755
--- a/sources/scala/tools/nsc/ast/TreeGen.scala
+++ b/sources/scala/tools/nsc/ast/TreeGen.scala
@@ -43,10 +43,10 @@ abstract class TreeGen {
/** 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 */
+ /** Replaces 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))
+ if (tree.symbol.isStable) tree.setType(singleType(tree.symbol.owner.thisType, tree.symbol))
else tree
case Select(qual, _) =>
if (tree.symbol.isStable && qual.tpe.isStable) tree.setType(singleType(qual.tpe, tree.symbol))
@@ -62,12 +62,12 @@ abstract class TreeGen {
def TypeTree(tp: Type) = global.TypeTree() setType tp;
def This(sym: Symbol) =
- global.This(sym.name) setSymbol sym setType sym.thisType;
+ typer.transformQualExpr(global.This(sym.name) setSymbol sym);
def Ident(sym: Symbol) = {
assert(sym.isTerm);
sym.setFlag(ACCESSED);
- global.Ident(sym.name) setSymbol sym setType sym.tpe;
+ typer.transformExpr(global.Ident(sym.name) setSymbol sym);
}
def Select(qual: Tree, sym: Symbol) = {
@@ -76,24 +76,16 @@ abstract class TreeGen {
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)
- setSymbol sym setType UnitClass.tpe
+ setSymbol sym setType NoType
}
def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree);
def AbsTypeDef(sym: Symbol) = atPos(sym.pos) {
global.AbsTypeDef(flags2mods(sym.flags), sym.name,
TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi))
- setSymbol sym setType UnitClass.tpe
+ setSymbol sym setType NoType
}
def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree) = atPos(sym.pos) {
@@ -113,7 +105,7 @@ abstract class TreeGen {
vparamss.map(.map(ValDef)),
TypeTree(tpe),
rhs(vparamss))
- setSymbol sym setType UnitClass.tpe
+ setSymbol sym setType NoType
}
mk(List(), List(), sym.tpe)
}
diff --git a/sources/scala/tools/nsc/ast/TreeInfo.scala b/sources/scala/tools/nsc/ast/TreeInfo.scala
index 8167ef00d7..c0ffe8f4b3 100644
--- a/sources/scala/tools/nsc/ast/TreeInfo.scala
+++ b/sources/scala/tools/nsc/ast/TreeInfo.scala
@@ -78,9 +78,8 @@ abstract class TreeInfo {
/** Is tree a pure constructor?
*/
def isPureConstr(tree: Tree): boolean = tree match {
- case Ident(_)
- | Select(_, _) =>
- tree.symbol != null && tree.symbol.isPrimaryConstructor;
+ case Ident(_) | Select(_, _) =>
+ tree.symbol.isPrimaryConstructor
case TypeApply(fn, _) =>
isPureConstr(fn)
case Apply(fn, List()) =>
@@ -141,13 +140,6 @@ abstract class TreeInfo {
case _ => false
}
- /** The method symbol of an application node, or NoSymbol, if none exists.
- */
- def methSymbol(tree: Tree): Symbol = {
- val meth = methPart(tree);
- if (meth.hasSymbol) meth.symbol else NoSymbol
- }
-
/** The method part of an application node
*/
def methPart(tree: Tree): Tree = tree match {
diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala
index 8d5d061fcf..96aa8b26dc 100644
--- a/sources/scala/tools/nsc/ast/TreePrinters.scala
+++ b/sources/scala/tools/nsc/ast/TreePrinters.scala
@@ -74,8 +74,7 @@ abstract class TreePrinters {
}
def symName(tree: Tree, name: Name): String =
- if (tree.symbol != null && tree.symbol != NoSymbol) tree.symbol.nameString
- else name.toString();
+ if (tree.symbol != NoSymbol) tree.symbol.nameString else name.toString();
def printOpt(prefix: String, tree: Tree): unit =
if (!tree.isEmpty) { print(prefix); print(tree) }
diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala
index 52b73b5804..d0db368a81 100644
--- a/sources/scala/tools/nsc/ast/Trees.scala
+++ b/sources/scala/tools/nsc/ast/Trees.scala
@@ -117,11 +117,17 @@ abstract class Trees: Global {
/** Attribuetd definition */
case class Attributed(attribute: Tree, definition: Tree)
- extends Tree;
+ extends Tree {
+ override def symbol: Symbol = definition.symbol;
+ override def symbol_=(sym: Symbol): unit = { definition.symbol = sym }
+ }
/** Documented definition, eliminated by analyzer */
case class DocDef(comment: String, definition: Tree)
- extends Tree;
+ extends Tree {
+ override def symbol: Symbol = definition.symbol;
+ override def symbol_=(sym: Symbol): unit = { definition.symbol = sym }
+ }
/** Instantiation template */
case class Template(parents: List[Tree], body: List[Tree])
@@ -165,7 +171,7 @@ abstract class Trees: Global {
/** Return expression */
case class Return(expr: Tree)
- extends SymTree with TermTree;
+ extends TermTree with SymTree;
case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree)
extends TermTree;
@@ -186,11 +192,17 @@ abstract class Trees: Global {
/** Type application */
case class TypeApply(fun: Tree, args: List[Tree])
- extends TermTree;
+ extends TermTree {
+ override def symbol: Symbol = fun.symbol;
+ override def symbol_=(sym: Symbol): unit = { fun.symbol = sym }
+ }
/** Value application */
case class Apply(fun: Tree, args: List[Tree])
- extends TermTree;
+ extends TermTree {
+ override def symbol: Symbol = fun.symbol;
+ override def symbol_=(sym: Symbol): unit = { fun.symbol = sym }
+ }
/** Super reference */
case class Super(qual: Name, mixin: Name)
@@ -216,7 +228,10 @@ abstract class Trees: Global {
/** Literal */
case class Literal(value: Any)
- extends TermTree;
+ extends TermTree {
+ // todo: change hashcode generation to make this superfluous
+ override def hashCode(): int = if (value == null) 0 else value.hashCode() * 41 + 17;
+ }
/** General type term, introduced by RefCheck. */
case class TypeTree() extends TypTree {
@@ -237,7 +252,10 @@ abstract class Trees: Global {
/** Applied type, eliminated by RefCheck */
case class AppliedTypeTree(tpt: Tree, args: List[Tree])
- extends TypTree;
+ extends TypTree {
+ override def symbol: Symbol = tpt.symbol;
+ override def symbol_=(sym: Symbol): unit = { tpt.symbol = sym }
+ }
/* A standard pattern match
case EmptyTree =>
diff --git a/sources/scala/tools/nsc/ast/parser/Parsers.scala b/sources/scala/tools/nsc/ast/parser/Parsers.scala
index 8e0ef42c1f..b104a0e819 100755
--- a/sources/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/sources/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1655,11 +1655,12 @@ abstract class Parsers: ParserPhase {
/** Attribute ::= StableId [TypeArgs] [`(' [Exprs] `)']
*/
def attribute(): Tree = {
+ val pos = in.pos;
var t: Tree = convertToTypeId(stableId());
if (in.token == LBRACKET)
t = atPos(in.pos)(AppliedTypeTree(t, typeArgs()));
val args = if (in.token == LPAREN) argumentExprs() else List();
- makeNew(List(t), List(), args)
+ atPos(pos) { makeNew(List(t), List(), args) }
}
def joinAttributes(attrs: List[Tree], defs: List[Tree]): List[Tree] =
@@ -1724,23 +1725,24 @@ abstract class Parsers: ParserPhase {
* | package QualId `{' TopStatSeq `}'
* | TopStatSeq
*/
- def compilationUnit(): Tree = {
- if (in.token == PACKAGE) {
- val pos = in.skipToken();
- val pkg = qualId();
- if (in.token == SEMI) {
+ def compilationUnit(): Tree =
+ atPos(in.pos) {
+ if (in.token == PACKAGE) {
in.nextToken();
- makePackaging(pkg, topStatSeq()) setPos pos;
+ val pkg = qualId();
+ if (in.token == SEMI) {
+ in.nextToken();
+ makePackaging(pkg, topStatSeq())
+ } else {
+ accept(LBRACE);
+ val t = makePackaging(pkg, topStatSeq());
+ accept(RBRACE);
+ t
+ }
} else {
- accept(LBRACE);
- val t = makePackaging(pkg, topStatSeq());
- accept(RBRACE);
- t
+ makePackaging(Ident(nme.EMPTY_PACKAGE_NAME), topStatSeq())
}
- } else {
- makePackaging(Ident(nme.EMPTY_PACKAGE_NAME), topStatSeq())
}
- }
}
}
diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala
index 77e71141c5..45e6ac28dc 100755
--- a/sources/scala/tools/nsc/symtab/StdNames.scala
+++ b/sources/scala/tools/nsc/symtab/StdNames.scala
@@ -76,6 +76,7 @@ abstract class StdNames: SymbolTable {
def TUPLE_FIELD(index: int) = newTermName(TUPLE_FIELD_PREFIX_STRING + index);
def SETTER_NAME(name: Name) = encode(name.toString() + "_=");
+ def LOCAL_NAME(name: Name) = encode(name.toString() + " ");
val ERROR = newTermName("<error>");
val ERRORtype = newTypeName("<error>");
diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala
index b921431f4b..56a72ed968 100755
--- a/sources/scala/tools/nsc/symtab/Types.scala
+++ b/sources/scala/tools/nsc/symtab/Types.scala
@@ -22,7 +22,9 @@ import Flags._;
case ClassInfoType(parents, defs, clazz) =>
case MethodType(paramtypes, result) =>
case PolyType(tparams, result) =>
+ // the last three types are not used after phase `typer'.
case OverloadedType(pre, tparams, alts) =>
+ case AntiPolyType(pre: Type, targs) =>
case TypeVar(_, _) =>
*/
@@ -706,23 +708,33 @@ abstract class Types: SymbolTable {
}
}
+ /** A class containing the alternatives and type prefix of an overloaded symbol.
+ * Not used after phase `typer'.
+ */
+ case class OverloadedType(pre: Type, alternatives: List[Symbol]) extends Type {
+ override def prefix: Type = pre;
+ override def toString() = (alternatives map pre.memberType).mkString("", " <and> ", "")
+ }
+
+ /** A class remembering a type instantiation for some a set of overloaded polymorphic symbols.
+ * Not used after phase `typer'.
+ */
+ case class AntiPolyType(pre: Type, targs: List[Type]) extends Type {
+ override def toString() = pre.toString() + targs.mkString("(with type arguments ", ",", ")");
+ override def memberType(sym: Symbol) = pre.memberType(sym) match {
+ case PolyType(tparams, restp) => restp.subst(tparams, targs)
+ }
+ }
+
/** A class representing a type variable
+ * Not used after phase `typer'.
*/
case class TypeVar(origin: Type, constr: TypeConstraint) extends Type {
-
override def symbol = origin.symbol;
-
override def toString(): String =
if (constr.inst == NoType) "?" + origin else constr.inst.toString();
}
- /** A class containing the alternatives and type prefix of an overloaded symbol
- */
- case class OverloadedType(pre: Type, alternatives: List[Symbol]) extends Type {
- override def prefix: Type = pre;
- override def toString() = (alternatives map pre.memberType).mkString("", " <and> ", "")
- }
-
/** A class representing an as-yet unevaluated type.
*/
abstract class LazyType extends Type {
@@ -881,6 +893,11 @@ abstract class Types: SymbolTable {
val pre1 = this(pre);
if (pre1 eq pre) tp
else OverloadedType(pre1, alts)
+ case AntiPolyType(pre, args) =>
+ val pre1 = this(pre);
+ val args1 = List.mapConserve(args)(this);
+ if ((pre1 eq pre) && (args1 eq args)) tp
+ else AntiPolyType(pre1, args1)
case TypeVar(_, constr) =>
if (constr.inst != NoType) this(constr.inst)
else tp
@@ -1068,14 +1085,14 @@ abstract class Types: SymbolTable {
case Pair(_, WildcardType) => true
case Pair(NoType, _) => false
- case Pair(NoPrefix, _) => false
+ case Pair(NoPrefix, _) => tp2.symbol.isPackageClass
case Pair(_, NoType) => false
- case Pair(_, NoPrefix) => false
+ case Pair(_, NoPrefix) => tp1.symbol.isPackageClass
case Pair(ThisType(sym1), ThisType(sym2)) =>
sym1 == sym2
case Pair(SingleType(pre1, sym1), SingleType(pre2, sym2))
- if (sym1 == sym2 && pre1 =:= pre2) =>
+ if ((sym1 == sym2) && (pre1 =:= pre2)) =>
true
/*
case Pair(SingleType(pre1, sym1), ThisType(sym2))
@@ -1143,9 +1160,9 @@ abstract class Types: SymbolTable {
case Pair(_, WildcardType) => true
case Pair(NoType, _) => false
- case Pair(NoPrefix, _) => false
+ case Pair(NoPrefix, _) => tp2.symbol.isPackageClass
case Pair(_, NoType) => false
- case Pair(_, NoPrefix) => false
+ case Pair(_, NoPrefix) => tp1.symbol.isPackageClass
case Pair(ThisType(_), ThisType(_)) => tp1 =:= tp2
case Pair(ThisType(_), SingleType(_, _)) => tp1 =:= tp2
diff --git a/sources/scala/tools/nsc/symtab/classfile/Pickle.scala b/sources/scala/tools/nsc/symtab/classfile/Pickle.scala
deleted file mode 100644
index e7f1271761..0000000000
--- a/sources/scala/tools/nsc/symtab/classfile/Pickle.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-/* NSC -- new scala compiler
- * Copyright 2005 LAMP/EPFL
- * @author Martin Odersky
- */
-// $Id$
-package scala.tools.nsc.symtab.classfile;
-
-/***************************************************
- * Symbol table attribute format: see EntryTags.java
- */
-class Pickle {}
diff --git a/sources/scala/tools/nsc/typechecker/ConstantFolder.scala b/sources/scala/tools/nsc/typechecker/ConstantFolder.scala
index 83530cdd34..6fa914ea45 100755
--- a/sources/scala/tools/nsc/typechecker/ConstantFolder.scala
+++ b/sources/scala/tools/nsc/typechecker/ConstantFolder.scala
@@ -14,23 +14,22 @@ abstract class ConstantFolder {
private val NoValue = new Object();
/** If tree is a constant operation, replace with result. */
- def apply(tree: Tree): Tree = {
- val newvalue = tree match {
- case Apply(Select(Literal(x), op), List(Literal(y))) => foldBinop(op, x, y)
- case Select(Literal(x), op) => foldUnop(op, x)
- case _ => NoValue
- }
- if (newvalue != NoValue) Literal(newvalue) else tree
- }
+ def apply(tree: Tree): Tree = fold(tree, tree match {
+ case Apply(Select(Literal(x), op), List(Literal(y))) => foldBinop(op, x, y)
+ case Select(Literal(x), op) => foldUnop(op, x)
+ case _ => NoValue
+ });
/** If tree is a constant value that can be converted to type `pt', perform the conversion */
- def apply(tree: Tree, pt: Type): Tree = {
- val newvalue = tree match {
- case Literal(value) => foldTyped(value, pt)
- case _ => NoValue
- }
- if (newvalue != NoValue) Literal(newvalue) else tree
- }
+ def apply(tree: Tree, pt: Type): Tree = fold(tree, tree match {
+ case Literal(value) => foldTyped(value, pt)
+ case _ => NoValue
+ });
+
+ def fold(tree: Tree, value: Any): Tree =
+ if (value != NoValue)
+ copy.Literal(tree, value) setType ConstantType(literalType(value), value)
+ else tree;
private def foldUnop(op: Name, value: Any): Any = Pair(op, value) match {
case Pair(nme.ZNOT, x: boolean) => !x
@@ -182,4 +181,18 @@ abstract class ConstantFolder {
NoValue
}
}
+
+ def literalType(value: Any): Type =
+ if (value.isInstanceOf[unit]) UnitClass.tpe
+ else if (value.isInstanceOf[boolean]) BooleanClass.tpe
+ else if (value.isInstanceOf[byte]) ByteClass.tpe
+ else if (value.isInstanceOf[short]) ShortClass.tpe
+ else if (value.isInstanceOf[char]) CharClass.tpe
+ else if (value.isInstanceOf[int]) IntClass.tpe
+ else if (value.isInstanceOf[long]) LongClass.tpe
+ else if (value.isInstanceOf[float]) FloatClass.tpe
+ else if (value.isInstanceOf[double]) DoubleClass.tpe
+ else if (value.isInstanceOf[String]) StringClass.tpe
+ else if (value == null) AllRefClass.tpe
+ else throw new FatalError("unexpected literal value: " + value);
}
diff --git a/sources/scala/tools/nsc/typechecker/Contexts.scala b/sources/scala/tools/nsc/typechecker/Contexts.scala
index 2ab5457fa9..85bc6e9d74 100755
--- a/sources/scala/tools/nsc/typechecker/Contexts.scala
+++ b/sources/scala/tools/nsc/typechecker/Contexts.scala
@@ -157,7 +157,7 @@ class Contexts: Analyzer {
if (c.outer.enclClass == null) assert(false, "accessWithin(" + owner + ") " + c);//debug
c = c.outer.enclClass;
}
- c != NoContext;
+ c != NoContext
}
/** Is `clazz' a subclass of an enclosing class? */
@@ -171,7 +171,7 @@ class Contexts: Analyzer {
||
(!sym.hasFlag(PRIVATE | PROTECTED))
||
- accessWithin(sym.owner) && (!sym.hasFlag(LOCAL) || pre.isInstanceOf[ThisType])
+ accessWithin(sym.owner) && (!sym.hasFlag(LOCAL) || pre =:= sym.owner.thisType)
||
(!sym.hasFlag(PRIVATE) &&
(superAccess ||
diff --git a/sources/scala/tools/nsc/typechecker/EtaExpansion.scala b/sources/scala/tools/nsc/typechecker/EtaExpansion.scala
index 8ead3de9ae..3403d6f5d1 100644
--- a/sources/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/sources/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -39,16 +39,16 @@ abstract class EtaExpansion: Analyzer {
if (treeInfo.isPureExpr(tree)) tree
else {
val vname: Name = freshName();
- defs += ValDef(SYNTHETIC, vname, TypeTree(), tree);
- Ident(vname)
+ defs += atPos(tree.pos)(ValDef(SYNTHETIC, vname, TypeTree(), tree));
+ Ident(vname) setPos tree.pos
}
tree match {
case Apply(fn, args) =>
- copy.Apply(tree, liftoutPrefix(fn), List.mapConserve(args)(liftout));
+ copy.Apply(tree, liftoutPrefix(fn), List.mapConserve(args)(liftout)) setType null
case TypeApply(fn, args) =>
- copy.TypeApply(tree, liftoutPrefix(fn), args)
+ copy.TypeApply(tree, liftoutPrefix(fn), args) setType null
case Select(qual, name) =>
- copy.Select(tree, liftout(qual), name)
+ copy.Select(tree, liftout(qual), name) setSymbol NoSymbol setType null
case Ident(name) =>
tree
}
@@ -60,7 +60,7 @@ abstract class EtaExpansion: Analyzer {
val params = formals map (formal =>
ValDef(SYNTHETIC | PARAM, freshName(), TypeTree().setType(formal), EmptyTree));
val args = params map (param => Ident(param.name));
- Function(params, expand(Apply(tree, args), restpe))
+ atPos(tree.pos)(Function(params, expand(Apply(tree, args), restpe)))
case _ =>
tree
}
diff --git a/sources/scala/tools/nsc/typechecker/Infer.scala b/sources/scala/tools/nsc/typechecker/Infer.scala
index 814d84bd9f..4ce8d7f8d8 100755
--- a/sources/scala/tools/nsc/typechecker/Infer.scala
+++ b/sources/scala/tools/nsc/typechecker/Infer.scala
@@ -482,35 +482,35 @@ abstract class Infer: Analyzer {
* If several alternatives match `pt', take parameterless one.
* Error if no or several such alternatives exist.
*/
- def inferExprAlternative(tree: Tree, pt: Type): unit = tryTwice {
- val pre = tree.symbol.info.prefix;
- val alts = tree.symbol.alternatives filter (alt =>
- isCompatible(pre.memberType(alt), pt));
- def improves(sym1: Symbol, sym2: Symbol): boolean =
- sym2 == NoSymbol ||
- ((sym1.owner isSubClass sym2.owner) &&
- {val tp1 = pre.memberType(sym1);
- val tp2 = pre.memberType(sym2);
- tp2 == ErrorType ||
- !global.infer.isCompatible(tp2, pt) && global.infer.isCompatible(tp1, pt) ||
- (tp2.paramSectionCount > 0) && (tp1.paramSectionCount == 0 || specializes(tp1, tp2))
- });
- val best = ((NoSymbol: Symbol) /: alts) ((best, alt) =>
- if (improves(alt, best)) alt else best);
- val competing = alts dropWhile (alt => best == alt || improves(best, alt));
- if (best == NoSymbol) {
- tree match {//debug
- case Select(qual, _) =>
- System.out.println("qual: " + qual + ":" + qual.tpe + " with decls " + qual.tpe.decls + " with members " + qual.tpe.members + " with members " + qual.tpe.member(newTermName("$minus")));
- case _ =>
+ def inferExprAlternative(tree: Tree, pt: Type): unit = tree.tpe match {
+ case OverloadedType(pre, alts) => tryTwice {
+ val alts1 = alts filter (alt => isCompatible(pre.memberType(alt), pt));
+ def improves(sym1: Symbol, sym2: Symbol): boolean =
+ sym2 == NoSymbol ||
+ ((sym1.owner isSubClass sym2.owner) &&
+ {val tp1 = pre.memberType(sym1);
+ val tp2 = pre.memberType(sym2);
+ tp2 == ErrorType ||
+ !global.infer.isCompatible(tp2, pt) && global.infer.isCompatible(tp1, pt) ||
+ (tp2.paramSectionCount > 0) && (tp1.paramSectionCount == 0 || specializes(tp1, tp2))
+ });
+ val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) =>
+ if (improves(alt, best)) alt else best);
+ val competing = alts1 dropWhile (alt => best == alt || improves(best, alt));
+ if (best == NoSymbol) {
+ tree match {//debug
+ case Select(qual, _) =>
+ System.out.println("qual: " + qual + ":" + qual.tpe + " with decls " + qual.tpe.decls + " with members " + qual.tpe.members + " with members " + qual.tpe.member(newTermName("$minus")));
+ case _ =>
+ }
+ typeErrorTree(tree, tree.symbol.tpe, pt)
+ } else if (!competing.isEmpty) {
+ context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt);
+ setError(tree);
+ ()
+ } else {
+ tree.setSymbol(best).setType(pre.memberType(best))
}
- typeErrorTree(tree, tree.symbol.tpe, pt)
- } else if (!competing.isEmpty) {
- context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt);
- setError(tree);
- ()
- } else {
- tree.setSymbol(best).setType(pre.memberType(best))
}
}
@@ -522,33 +522,33 @@ abstract class Infer: Analyzer {
* with pt = WildcardType.
* Otherwise, if there is no best alternative, error.
*/
- def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], argtpes: List[Type], pt: Type): unit = tryTwice {
- val pre = tree.symbol.info.prefix;
- if (settings.debug.value) System.out.println("infer method alt " + tree.symbol + " with alternatives " + (tree.symbol.alternatives map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt);//debug
- val alts = tree.symbol.alternatives filter (alt =>
- isApplicable(undetparams, pre.memberType(alt), argtpes, pt));
- def improves(sym1: Symbol, sym2: Symbol) = {
- sym2 == NoSymbol ||
- ((sym1.owner isSubClass sym2.owner) &&
- specializes(pre.memberType(sym1), pre.memberType(sym2)))
- }
- val best = ((NoSymbol: Symbol) /: alts) ((best, alt) =>
- if (improves(alt, best)) alt else best);
- val competing = alts dropWhile (alt => best == alt || improves(best, alt));
- if (best == NoSymbol) {
- if (pt == WildcardType) {
- errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
+ def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], argtpes: List[Type], pt: Type): unit = tree.tpe match {
+ case OverloadedType(pre, alts) => tryTwice {
+ if (settings.debug.value) System.out.println("infer method alt " + tree.symbol + " with alternatives " + (alts map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt);//debug
+ val alts1 = alts filter (alt => isApplicable(undetparams, pre.memberType(alt), argtpes, pt));
+ def improves(sym1: Symbol, sym2: Symbol) = {
+ sym2 == NoSymbol ||
+ ((sym1.owner isSubClass sym2.owner) &&
+ specializes(pre.memberType(sym1), pre.memberType(sym2)))
+ }
+ val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) =>
+ if (improves(alt, best)) alt else best);
+ val competing = alts1 dropWhile (alt => best == alt || improves(best, alt));
+ if (best == NoSymbol) {
+ if (pt == WildcardType) {
+ errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
+ } else {
+ inferMethodAlternative(tree, undetparams, argtpes, WildcardType)
+ }
+ } else if (!competing.isEmpty) {
+ context.ambiguousError(tree.pos, pre, best, competing.head,
+ "argument types " + argtpes.mkString("(", ",", ")") +
+ (if (pt == WildcardType) "" else " and expected result type " + pt));
+ setError(tree);
+ ()
} else {
- inferMethodAlternative(tree, undetparams, argtpes, WildcardType)
+ tree.setSymbol(best).setType(pre.memberType(best))
}
- } else if (!competing.isEmpty) {
- context.ambiguousError(tree.pos, pre, best, competing.head,
- "argument types " + argtpes.mkString("(", ",", ")") +
- (if (pt == WildcardType) "" else " and expected result type " + pt));
- setError(tree);
- ()
- } else {
- tree.setSymbol(best).setType(pre.memberType(best))
}
}
@@ -572,23 +572,24 @@ abstract class Infer: Analyzer {
* as the number of type parameters, if it exists.
* If several or none such polymorphic alternatives exist, error.
*/
- def inferPolyAlternative(tree: Tree, nparams: int): unit = {
- val pre = tree.symbol.info.prefix;
- val alts = tree.symbol.alternatives filter (alt =>
- alt.typeParams.length == nparams);
- if (alts.isEmpty) {
- errorTree(tree,
- if (tree.symbol.alternatives exists (alt => alt.typeParams.length > 0))
- "wrong number of type parameters for " + treeSymTypeMsg(tree)
- else treeSymTypeMsg(tree) + " does not take type parameters")
- } else if (!alts.tail.isEmpty) {
- context.ambiguousError(tree.pos, pre, alts.head, alts.tail.head,
- "polymorphic function with " + nparams + " parameters");
- setError(tree);
- ()
- } else {
- tree.setSymbol(alts.head).setType(pre.memberType(alts.head))
- }
+ def inferPolyAlternatives(tree: Tree, nparams: int): unit = tree.tpe match {
+ case OverloadedType(pre, alts) =>
+ val sym = tree.symbol filter (alt => alt.typeParams.length == nparams);
+ if (sym == NoSymbol) {
+ errorTree(tree,
+ if (alts exists (alt => alt.typeParams.length > 0))
+ "wrong number of type parameters for " + treeSymTypeMsg(tree)
+ else treeSymTypeMsg(tree) + " does not take type parameters")
+ } else if (sym.hasFlag(OVERLOADED)) {
+ val tparams = sym.alternatives.head.typeParams;
+ val tpe =
+ PolyType(tparams,
+ OverloadedType(AntiPolyType(pre, tparams map (.tpe)), sym.alternatives));
+ sym.setInfo(tpe);
+ tree.setSymbol(sym).setType(tpe);
+ } else {
+ tree.setSymbol(sym).setType(pre.memberType(sym))
+ }
}
}
}
diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala
index 01dc7cbe90..5c26880563 100755
--- a/sources/scala/tools/nsc/typechecker/Namers.scala
+++ b/sources/scala/tools/nsc/typechecker/Namers.scala
@@ -121,7 +121,7 @@ trait Namers: Analyzer {
}
def finish = finishWith(List());
- if (tree.symbol == null || tree.symbol == NoSymbol) {
+ if (tree.symbol == NoSymbol) {
val owner = context.owner;
tree match {
case PackageDef(name, stats) =>
@@ -151,14 +151,16 @@ trait Namers: Analyzer {
enterInScope(getter);
if ((mods & MUTABLE) != 0) {
val setter = owner.newMethod(tree.pos, nme.SETTER_NAME(name))
- .setFlag(accmods).setInfo(innerNamer.setterTypeCompleter(tree));
+ .setFlag(accmods & ~STABLE).setInfo(innerNamer.setterTypeCompleter(tree));
enterInScope(setter)
}
tree.symbol =
- if ((mods & DEFERRED) == 0)
- owner.newValue(tree.pos, name)
- .setFlag(mods & FieldFlags | PRIVATE | LOCAL).setInfo(innerNamer.typeCompleter(tree))
- else getter;
+ if ((mods & DEFERRED) == 0)
+ enterInScope(
+ owner.newValue(tree.pos, nme.LOCAL_NAME(name))
+ .setFlag(mods & FieldFlags | PRIVATE | LOCAL)
+ .setInfo(innerNamer.typeCompleter(tree)))
+ else getter;
} else {
tree.symbol =
enterInScope(owner.newValue(tree.pos, name).setFlag(mods));
diff --git a/sources/scala/tools/nsc/typechecker/TreeCheckers.scala b/sources/scala/tools/nsc/typechecker/TreeCheckers.scala
index fe56b35ea3..907275bc2d 100644
--- a/sources/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/sources/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -11,6 +11,8 @@ abstract class TreeCheckers extends Analyzer {
import global._;
+ val tpeOfTree = new scala.collection.mutable.HashMap[Tree, Type];
+
def checkTrees: unit = {
System.out.println("[consistency check at start of phase " + phase + "]");
for (val unit <- units) check(unit);
@@ -21,7 +23,11 @@ abstract class TreeCheckers extends Analyzer {
reporter.prompt(true);
val context = startContext.make(unit);
context.checking = true;
- new TreeChecker(context).transformExpr(unit.body);
+ tpeOfTree.clear;
+ val checker = new TreeChecker(context);
+ checker.precheck.traverse(unit.body);
+ checker.transformExpr(unit.body);
+ checker.postcheck.traverse(unit.body);
reporter.prompt(curPrompt);
}
@@ -32,23 +38,47 @@ abstract class TreeCheckers extends Analyzer {
import infer._;
override def transform(tree: Tree, mode: int, pt: Type): Tree = {
- System.out.println("**** checking " + tree);//debug
- if (tree.pos == Position.NOPOS)
- error(tree.pos, "tree without position: " + tree)
- else if (phase.id > typeCheckPhase.id)
- if (tree.tpe == null)
- error(tree.pos, "tree without type: " + tree);
- else {
- val oldtpe = tree.tpe;
- tree.tpe = null;
+ //System.out.println("**** checking " + tree);//debug
+ tree match {
+ case EmptyTree | TypeTree() =>
+ ;
+ case _ =>
+ if (!tpeOfTree.contains(tree)) {
+ tpeOfTree.update(tree, tree.tpe);
+ tree.tpe = null
+ }
val newtree = super.transform(tree, mode, pt);
if (newtree ne tree)
- error(tree.pos, "trees differ\n old: " + tree + "\n new: " + newtree);
- else if (!(oldtpe =:= newtree.tpe))
- error(tree.pos, "types differ\n old: " + oldtpe + "\n new: " + newtree.tpe);
- tree.tpe = oldtpe
- }
+ error(tree.pos, "trees differ\n old: " + tree + " [" + tree.getClass() + "]\n new: " +
+ newtree + " [" + newtree.getClass() + "]");
+ }
tree
}
+
+ object precheck extends Traverser {
+ override def traverse(tree: Tree): unit = {
+ if (tree.pos == Position.NOPOS)
+ error(tree.pos, "tree without position: " + tree)
+ else if (tree.tpe == null && phase.id >= typeCheckPhase.id)
+ error(tree.pos, "tree without type: " + tree)
+ }
+ }
+
+ object postcheck extends Traverser {
+ override def traverse(tree: Tree): unit = tree match {
+ case EmptyTree | TypeTree() =>
+ ;
+ case _ =>
+ tpeOfTree.get(tree) match {
+ case Some(oldtpe) =>
+ if (!(oldtpe =:= tree.tpe))
+ error(tree.pos, "types differ\n old: " + oldtpe + "\n new: " + tree.tpe +
+ "\n tree: " + tree);
+ tree.tpe = oldtpe;
+ super.traverse(tree)
+ case None =>
+ }
+ }
+ }
}
}
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index 685e6837f2..c0fa939ba8 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -86,6 +86,9 @@ abstract class Typers: Analyzer {
// of a type application. When set we do not
// decompose PolyTypes.
+ private val SUPERCONSTRmode = 0x100;// Set for the `super' in a superclass constructor call
+ // super.<init>
+
private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode;
/** Report a type error.
@@ -182,22 +185,26 @@ abstract class Typers: Analyzer {
})
}
- private def literalType(value: Any): Type =
- if (value.isInstanceOf[unit]) UnitClass.tpe
- else if (value.isInstanceOf[boolean]) BooleanClass.tpe
- else if (value.isInstanceOf[byte]) ByteClass.tpe
- else if (value.isInstanceOf[short]) ShortClass.tpe
- else if (value.isInstanceOf[char]) CharClass.tpe
- else if (value.isInstanceOf[int]) IntClass.tpe
- else if (value.isInstanceOf[long]) LongClass.tpe
- else if (value.isInstanceOf[float]) FloatClass.tpe
- else if (value.isInstanceOf[double]) DoubleClass.tpe
- else if (value.isInstanceOf[String]) StringClass.tpe
- else if (value == null) AllRefClass.tpe
- else throw new FatalError("unexpected literal value: " + value);
+ /** Post-process an identifier or selection node, performing the following:
+ * (1) Check that non-function pattern expressions are stable
+ * (2) Check that packages and static modules are not used as values
+ * (3) Turn tree type into stable type if possible and required by context. */
+ private def stabilize(tree: Tree, pre: Type, mode: int, pt: Type): Tree = {
+ if (tree.symbol.hasFlag(OVERLOADED) && (mode & FUNmode) == 0)
+ inferExprAlternative(tree, pt);
+ if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) // (1)
+ checkStable(tree)
+ else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !tree.symbol.isValue) // (2)
+ errorTree(tree, tree.symbol.toString() + " is not a value");
+ else if (tree.symbol.isStable && pre.isStable && tree.tpe.symbol != ByNameParamClass &&
+ (pt.isStable || (mode & QUALmode) != 0 || tree.symbol.isModule)) // (3)
+ tree.setType(singleType(pre, tree.symbol))
+ else tree
+ }
/** Perform the following adaptations of expression, pattern or type `tree' wrt to
* given mode `mode' and given prototype `pt':
+ * (0) Convert expressions with constant types to literals
* (1) Resolve overloading, unless mode contains FUNmode
* (2) Apply parameterless functions
* (3) Apply polymorphic types to fresh instances of their type parameters and
@@ -226,30 +233,31 @@ abstract class Typers: Analyzer {
*/
// def adapt(tree: Tree, mode: int, pt: Type): Tree = {
private def adapt(tree: Tree, mode: int, pt: Type): Tree = tree.tpe match {
+ case ConstantType(base, value) if (constfold.fold(tree, value) != tree) => // (0)
+ adapt(constfold.fold(tree, value), mode, pt)
+ case PolyType(List(), restp @ ConstantType(base, value)) => // (0)
+ adapt(constfold.fold(tree, value), mode, pt)
case OverloadedType(pre, alts) if ((mode & FUNmode) == 0) => // (1)
inferExprAlternative(tree, pt);
adapt(tree, mode, pt)
case PolyType(List(), restpe) => // (2)
- transform(constfold(tree.setType(restpe)), mode, pt);
+ adapt(tree setType restpe, mode, pt);
case TypeRef(_, sym, List(arg))
if ((mode & EXPRmode) != 0 && sym == ByNameParamClass) => // (2)
adapt(tree setType arg, mode, pt);
case PolyType(tparams, restpe) if ((mode & TAPPmode) == 0) => // (3)
- if (tree.symbol != null) {
- if (settings.debug.value) System.out.println("adapting " + tree + " " + tree.symbol.tpe + " " + tree.symbol.getClass() + " " + tree.symbol.hasFlag(CASE));//debug
- }
+ if (settings.debug.value && tree.symbol != null) System.out.println("adapting " + tree + " " + tree.symbol.tpe + " " + tree.symbol.getClass() + " " + tree.symbol.hasFlag(CASE));//debug
val tparams1 = cloneSymbols(tparams);
val tree1 = if (tree.isType) tree
else TypeApply(tree, tparams1 map (tparam =>
- TypeTree() setPos tparam.pos setType tparam.tpe)) setPos tree.pos;
+ TypeTree() setPos tree.pos setType tparam.tpe)) setPos tree.pos;
context.undetparams = context.undetparams ::: tparams1;
adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt)
case mt: ImplicitMethodType if ((mode & (EXPRmode | FUNmode)) == EXPRmode) => // (4.1)
transform(applyImplicitArgs(tree), mode, pt)
case mt: MethodType if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
isCompatible(tree.tpe, pt)) => // (4.2)
- val meth = treeInfo.methSymbol(tree);
- if (meth.isConstructor) errorTree(tree, "missing arguments for " + meth)
+ if (tree.symbol.isConstructor) errorTree(tree, "missing arguments for " + tree.symbol)
else transform(etaExpand(tree), mode, pt)
case _ =>
if (tree.isType) {
@@ -281,7 +289,7 @@ abstract class Typers: Analyzer {
}
} else if ((mode & FUNmode) != 0) {
tree
- } else if (tree.symbol != null && !tree.symbol.unsafeTypeParams.isEmpty) { // (7)
+ } else if (tree.hasSymbol && !tree.symbol.unsafeTypeParams.isEmpty) { // (7)
errorTree(tree, "" + clazz + " takes type parameters");
} else tree match { // (6)
case TypeTree() => tree
@@ -289,25 +297,24 @@ abstract class Typers: Analyzer {
}
} else if ((mode & (EXPRmode | FUNmode)) == (EXPRmode | FUNmode) &&
((mode & TAPPmode) == 0 || tree.tpe.typeParams.isEmpty) &&
- tree.tpe.member(nme.apply).filter(m => m.tpe.paramSectionCount > 0)
- != NoSymbol) { // (8)
- transform(Select(tree, nme.apply), mode, pt)
+ tree.tpe.member(nme.apply).filter(m => m.tpe.paramSectionCount > 0) != NoSymbol) { // (8)
+ transform(Select(tree, nme.apply) setPos tree.pos, mode, pt)
} else if (!context.undetparams.isEmpty & (mode & POLYmode) == 0) { // (9)
val tparams = context.undetparams;
context.undetparams = List();
inferExprInstance(tree, tparams, pt);
tree
} else if (tree.tpe <:< pt) {
- tree
+ tree
} else {
val tree1 = constfold(tree, pt); // (10) (11)
- if (tree1 != tree) transform(tree1, mode, pt);
+ if (tree1 != tree) adapt(tree1, mode, pt);
else {
if ((mode & (EXPRmode | FUNmode)) == EXPRmode) {
assert(pt != null);
assert(tree1.tpe != null, tree1);
if (pt.symbol == UnitClass && tree1.tpe <:< AnyClass.tpe) // (12)
- return transform(Block(List(tree), Literal(())), mode, pt)
+ return transform(atPos(tree.pos)(Block(List(tree), Literal(()))), mode, pt)
else if (context.reportGeneralErrors) { // (13); the condition prevents chains of views
val coercion = inferView(tree.pos, tree.tpe, pt, true);
if (coercion != EmptyTree)
@@ -337,10 +344,10 @@ abstract class Typers: Analyzer {
var mixins = templ.parents.tail map transformType;
// If first parent is trait, make it first mixin and add its superclass as first parent
if (supertpt.tpe.symbol != null && supertpt.tpe.symbol.initialize.isTrait) {
- mixins = supertpt :: mixins;
- supertpt = gen.TypeTree(supertpt.tpe.parents(0)) setPos supertpt.pos;
+ mixins = transformType(supertpt) :: mixins;
+ supertpt = gen.TypeTree(supertpt.tpe.parents.head) setPos supertpt.pos;
}
- if (supertpt.symbol != null) {
+ if (supertpt.hasSymbol) {
val tparams = supertpt.symbol.typeParams;
if (!tparams.isEmpty) {
val constr @ DefDef(_, _, _, vparamss, _, Apply(_, superargs)) =
@@ -428,27 +435,39 @@ abstract class Typers: Analyzer {
}
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))));
- }
- def getter: DefDef = {
- val sym = vd.symbol;
- val getter = sym.owner.info.decls.lookup(sym.name).suchThat(.hasFlag(ACCESSOR));
- val result = atPos(vd.pos)(gen.DefDef(getter, vparamss => gen.mkRef(sym)));
+ case ValDef(mods, name, tpe, rhs) if (mods & PRIVATE) == 0 =>
+ val vdef = copy.ValDef(stat, mods | PRIVATE | LOCAL, nme.LOCAL_NAME(name), tpe, rhs);
+ val getter: DefDef = {
+ val sym = vdef.symbol;
+ val getter = sym.owner.info.decls.lookup(name).suchThat(.hasFlag(ACCESSOR));
+ val result = atPos(vdef.pos)(
+ gen.DefDef(getter, vparamss =>
+ if ((mods & DEFERRED) != 0) EmptyTree
+ else stabilize(gen.mkRef(sym), sym.owner.thisType, EXPRmode, sym.tpe.deconst)));
checkNoEscaping.privates(result.symbol, result.tpt);
result
}
- if ((mods & MUTABLE) != 0) List(stat, getter, setter) else List(stat, getter)
+ def setter: DefDef = {
+ val sym = vdef.symbol;
+ val setter = sym.owner.info.decls.lookup(nme.SETTER_NAME(name)).suchThat(.hasFlag(ACCESSOR));
+ atPos(vdef.pos)(
+ gen.DefDef(setter, vparamss =>
+ if ((mods & DEFERRED) != 0) EmptyTree
+ else transformExpr(Assign(gen.mkRef(getter.symbol), gen.mkRef(vparamss.head.head)))))
+ }
+ val gs = if ((mods & MUTABLE) != 0) List(getter, setter) else List(getter);
+ if ((mods & DEFERRED) != 0) gs else vdef :: gs
+ case DocDef(comment, defn) =>
+ addGetterSetter(defn) map (stat => DocDef(comment, stat))
+ case Attributed(attr, defn) =>
+ addGetterSetter(defn) map (stat => Attributed(attr.duplicate, stat))
case _ =>
List(stat)
}
def transformTemplate(templ: Template): Template = {
- templ setSymbol context.owner.newLocalDummy(templ.pos);
+ if (templ.symbol == NoSymbol)
+ templ setSymbol context.owner.newLocalDummy(templ.pos);
val parents1 = parentTypes(templ);
val selfType =
if (context.owner.isAnonymousClass)
@@ -465,7 +484,8 @@ abstract class Typers: Analyzer {
var tpt1 = checkNoEscaping.privates(sym, transformType(vdef.tpt));
val rhs1 =
if (vdef.rhs.isEmpty) vdef.rhs
- else newTyper(context.make(vdef, sym)).transform(vdef.rhs, EXPRmode, tpt1.tpe.deconst);
+ else constfold(
+ newTyper(context.make(vdef, sym)).transform(vdef.rhs, EXPRmode, tpt1.tpe.deconst));
copy.ValDef(vdef, vdef.mods, vdef.name, tpt1, rhs1) setType NoType
}
@@ -581,7 +601,7 @@ abstract class Typers: Analyzer {
context = context.makeNewImport(imp);
EmptyTree
case _ =>
- (if (!stat.isDef && exprOwner != context.owner)
+ (if (exprOwner != context.owner && (!stat.isDef || stat.isInstanceOf[LabelDef]))
newTyper(context.make(stat, exprOwner)) else this).transformExpr(stat)
}
}
@@ -597,7 +617,7 @@ abstract class Typers: Analyzer {
def transformTypeApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match {
case OverloadedType(pre, alts) =>
- inferPolyAlternative(fun, args.length);
+ inferPolyAlternatives(fun, args.length);
transformTypeApply(fun, args)
case PolyType(tparams, restpe) if (tparams.length != 0) =>
if (tparams.length == args.length) {
@@ -636,9 +656,7 @@ abstract class Typers: Analyzer {
case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp
case _ => tp
}
- val tree1 = copy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe));
- val tree2 = constfold(tree1);
- if (tree1 == tree2) tree2 else transform(tree2, mode, pt)
+ constfold(copy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe)))
} else {
assert((mode & PATTERNmode) == 0); // this case cannot arise for patterns
val lenientTargs = protoTypeArgs(tparams, formals, restpe, pt);
@@ -694,7 +712,15 @@ abstract class Typers: Analyzer {
* `qual' is already attributed.
*/
def transformSelect(qual: Tree, name: Name): Tree = {
- val sym = qual.tpe.member(name);
+ val sym =
+ if (tree.symbol != NoSymbol) {
+ val alts = qual.tpe.member(name).alternatives;
+ if (alts.filter(tree.symbol.==).isEmpty)
+ assert(false, "symbol " + tree.symbol + " not in " + alts);
+ tree.symbol;
+ } else {
+ qual.tpe.member(name)
+ }
if (sym == NoSymbol && qual.isTerm && (qual.symbol == null || qual.symbol.isValue)) {
val coercion = inferView(qual.pos, qual.tpe, name, true);
if (coercion != EmptyTree)
@@ -711,7 +737,7 @@ abstract class Typers: Analyzer {
case Select(_, _) => copy.Select(tree, qual, name)
case SelectFromTypeTree(_, _) => copy.SelectFromTypeTree(tree, qual, name);
}
- stabilize(checkAccessible(tree1, sym, qual.tpe, qual), qual.tpe)
+ stabilize(checkAccessible(tree1, sym, qual.tpe, qual), qual.tpe, mode, pt);
}
}
@@ -725,104 +751,84 @@ abstract class Typers: Analyzer {
def ambiguousError(msg: String) =
error(tree.pos, "reference to " + name + " is ambiguous;\n" + msg);
- var defSym: Symbol = NoSymbol; // the directly found symbol
- var defEntry: ScopeEntry = null; // the scope entry of defSym, if defined in a local scope
+ var defSym: Symbol = tree.symbol; // the directly found symbol
var pre: Type = NoPrefix; // the prefix type of defSym, if a class member
+ var qual: Tree = EmptyTree; // the qualififier tree if transformed tree is a select
- var cx = context;
- while (defSym == NoSymbol && cx != NoContext) {
- pre = cx.enclClass.owner.thisType;
- defEntry = cx.scope.lookupEntry(name);
- if (defEntry != null)
- defSym = defEntry.sym
- else {
- cx = cx.enclClass;
- defSym = pre.member(name) filter (sym => context.isAccessible(sym, pre, false));
- if (defSym == NoSymbol) cx = cx.outer;
+ if (defSym == NoSymbol) {
+ var defEntry: ScopeEntry = null; // the scope entry of defSym, if defined in a local scope
+
+ var cx = context;
+ while (defSym == NoSymbol && cx != NoContext) {
+ pre = cx.enclClass.owner.thisType;
+ defEntry = cx.scope.lookupEntry(name);
+ if (defEntry != null)
+ defSym = defEntry.sym
+ else {
+ cx = cx.enclClass;
+ defSym = pre.member(name) filter (sym => context.isAccessible(sym, pre, false));
+ if (defSym == NoSymbol) cx = cx.outer;
+ }
+ }
+ val symDepth = if (defEntry == null) cx.depth
+ else cx.depth - (cx.scope.nestingLevel - defEntry.owner.nestingLevel);
+ var impSym: Symbol = NoSymbol; // the imported symbol
+ var imports = context.imports; // impSym != NoSymbol => it is imported from imports.head
+ while (impSym == NoSymbol && !imports.isEmpty && imports.head.depth > symDepth) {
+ impSym = imports.head.importedSymbol(name);
+ if (impSym == NoSymbol) imports = imports.tail;
}
- }
- val symDepth = if (defEntry == null) cx.depth
- else cx.depth - (cx.scope.nestingLevel - defEntry.owner.nestingLevel);
- var impSym: Symbol = NoSymbol; // the imported symbol
- var imports = context.imports; // impSym != NoSymbol => it is imported from imports.head
- while (impSym == NoSymbol && !imports.isEmpty && imports.head.depth > symDepth) {
- impSym = imports.head.importedSymbol(name);
- if (impSym == NoSymbol) imports = imports.tail;
- }
-
- // detect ambiguous definition/import,
- // update `defSym' to be the final resolved symbol,
- // 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
- // imported symbols take precedence over external package-owned symbols (hack?)
- if (defSym.tpe != NoType && impSym.tpe != NoType && defSym.isExternal && defSym.owner.isPackageClass)
- defSym = 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 && !defSym.isTypeParameter)
- qual = atPos(tree.pos)(gen.mkQualifier(pre));
- else
- pre = NoPrefix;
- } else {
- if (impSym.tpe != NoType) {
- var impSym1 = NoSymbol;
- var imports1 = imports.tail;
- def ambiguousImportError = ambiguousError(
- "it is imported twice in the same scope by\n" + imports.head + "\nand " + imports1.head);
- while (!imports1.isEmpty && imports1.head.depth == imports.head.depth) {
- var impSym1 = imports1.head.importedSymbol(name);
- if (impSym1 != NoSymbol) {
- if (imports1.head.isExplicitImport(name)) {
- if (imports.head.isExplicitImport(name)) ambiguousImportError;
- impSym = impSym1;
- imports = imports1;
- } else if (!imports.head.isExplicitImport(name)) ambiguousImportError
+ // detect ambiguous definition/import,
+ // update `defSym' to be the final resolved symbol,
+ // update `pre' to be `sym's prefix type in case it is an imported member,
+ // and compute value of:
+
+ // imported symbols take precedence over external package-owned symbols (hack?)
+ if (defSym.tpe != NoType && impSym.tpe != NoType && defSym.isExternal && defSym.owner.isPackageClass)
+ defSym = 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 && !defSym.isTypeParameter)
+ qual = atPos(tree.pos)(gen.mkQualifier(pre));
+ else
+ pre = NoPrefix;
+ } else {
+ if (impSym.tpe != NoType) {
+ var impSym1 = NoSymbol;
+ var imports1 = imports.tail;
+ def ambiguousImportError = ambiguousError(
+ "it is imported twice in the same scope by\n" + imports.head + "\nand " + imports1.head);
+ while (!imports1.isEmpty && imports1.head.depth == imports.head.depth) {
+ var impSym1 = imports1.head.importedSymbol(name);
+ if (impSym1 != NoSymbol) {
+ if (imports1.head.isExplicitImport(name)) {
+ if (imports.head.isExplicitImport(name)) ambiguousImportError;
+ impSym = impSym1;
+ imports = imports1;
+ } else if (!imports.head.isExplicitImport(name)) ambiguousImportError
+ }
+ imports1 = imports1.tail;
}
- imports1 = imports1.tail;
+ defSym = impSym;
+ qual = imports.head.qual;
+ pre = qual.tpe;
+ } else {
+ System.out.println(context);//debug
+ System.out.println(context.imports);//debug
+ error(tree.pos, "not found: " + decode(name));
+ defSym = context.owner.newErrorSymbol(name);
}
- defSym = impSym;
- qual = imports.head.qual;
- pre = qual.tpe;
- } else {
- System.out.println(context);//debug
- System.out.println(context.imports);//debug
- error(tree.pos, "not found: " + decode(name));
- defSym = context.owner.newErrorSymbol(name);
}
}
- 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:
- * (1) Turn trees of constant type into literals
- * (2) Check that non-function pattern expressions are stable
- * (3) Check that packages and static modules are not used as values
- * (4) Turn tree type into stable type if possible and required by context. */
- def stabilize(tree: Tree, pre: Type): Tree = tree.tpe match {
- case ConstantType(base, value) => // (1)
- Literal(value) setPos tree.pos setType tree.tpe
- case PolyType(List(), restp @ ConstantType(base, value)) => // (1)
- Literal(value) setPos tree.pos setType restp
- case _ =>
- if (tree.symbol.hasFlag(OVERLOADED) && (mode & FUNmode) == 0) {
- inferExprAlternative(tree, pt)
- }
- if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) // (2)
- checkStable(tree)
- else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !tree.symbol.isValue) // (3)
- errorTree(tree, tree.symbol.toString() + " is not a value");
- else if (tree.symbol.isStable && pre.isStable && tree.tpe.symbol != ByNameParamClass &&
- (pt.isStable || (mode & QUALmode) != 0 || tree.symbol.isModule)) // (4)
- tree.setType(singleType(pre, tree.symbol))
- else
- tree
+ val tree1 = if (qual == EmptyTree) tree
+ else atPos(tree.pos)(Select(qual, name));
+ // atPos necessary because qualifier might come from startContext
+ stabilize(checkAccessible(tree1, defSym, pre, qual), pre, mode, pt)
}
// begin transform1
@@ -906,7 +912,7 @@ abstract class Typers: Analyzer {
transform(
Apply(
Select(qual, nme.SETTER_NAME(name)) setPos lhs.pos,
- List(rhs)), mode, pt) setPos tree.pos
+ List(rhs)) setPos tree.pos, mode, pt)
}
} else if (varsym != null && varsym.isVariable) {
val rhs1 = transform(rhs, EXPRmode, lhs1.tpe);
@@ -934,7 +940,7 @@ abstract class Typers: Analyzer {
copy.Match(tree, selector1, cases1) setType lub(cases1 map (.tpe))
case Return(expr) =>
- val enclFun = context.owner.enclMethod;
+ val enclFun = if (tree.symbol != NoSymbol) tree.symbol else context.owner.enclMethod;
if (!enclFun.isMethod || enclFun.isConstructor)
errorTree(tree, "return outside method definition")
else if (!context.owner.hasFlag(INITIALIZED))
@@ -958,7 +964,7 @@ abstract class Typers: Analyzer {
case New(tpt: Tree) =>
var tpt1 = transform(tpt, TYPEmode | FUNmode, WildcardType);
- if (tpt1.symbol != null && !tpt1.symbol.typeParams.isEmpty) {
+ if (tpt1.hasSymbol && !tpt1.symbol.typeParams.isEmpty) {
context.undetparams = cloneSymbols(tpt1.symbol.unsafeTypeParams);
tpt1 = TypeTree()
setPos tpt1.pos
@@ -989,7 +995,7 @@ abstract class Typers: Analyzer {
var fun1 = transform(fun, funmode, funpt);
// if function is overloaded, filter all alternatives that match
// number of arguments and expected result type.
- if (settings.debug.value) System.out.println("trans app " + fun1 + ":" + fun1.symbol + ":" + fun1.tpe + " " + args);//debug
+ // if (settings.debug.value) System.out.println("trans app " + fun1 + ":" + fun1.symbol + ":" + fun1.tpe + " " + args);//DEBUG
if (fun1.hasSymbol && fun1.symbol.hasFlag(OVERLOADED)) {
val argtypes = args map (arg => AllClass.tpe);
val pre = fun1.symbol.tpe.prefix;
@@ -1002,11 +1008,13 @@ abstract class Typers: Analyzer {
transformApply(fun1, args)
case Super(qual, mix) =>
- val clazz = qualifyingClass(qual);
+ val clazz = if (tree.symbol != NoSymbol) tree.symbol else qualifyingClass(qual);
if (clazz == NoSymbol) setError(tree)
else {
val owntype =
- if (mix == nme.EMPTY.toTypeName) intersectionType(clazz.info.parents)
+ if (mix == nme.EMPTY.toTypeName)
+ if ((mode & SUPERCONSTRmode) != 0) clazz.info.parents.head
+ else intersectionType(clazz.info.parents)
else {
val ps = clazz.info.parents dropWhile (p => p.symbol.name != mix);
if (ps.isEmpty) {
@@ -1019,7 +1027,7 @@ abstract class Typers: Analyzer {
}
case This(qual) =>
- val clazz = qualifyingClass(qual);
+ val clazz = if (tree.symbol != NoSymbol) tree.symbol else qualifyingClass(qual);
if (clazz == NoSymbol) setError(tree)
else {
val owntype = if (pt.isStable || (mode & QUALmode) != 0) clazz.thisType
@@ -1028,12 +1036,8 @@ abstract class Typers: Analyzer {
}
case Select(qual @ Super(_, _), nme.CONSTRUCTOR) =>
- val qual1 = transform(qual, EXPRmode | QUALmode | POLYmode, WildcardType);
+ val qual1 = transform(qual, EXPRmode | QUALmode | POLYmode | SUPERCONSTRmode, 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) =>
@@ -1051,7 +1055,7 @@ abstract class Typers: Analyzer {
transformIdent(name);
case Literal(value) =>
- tree setType ConstantType(literalType(value), value)
+ tree setType ConstantType(constfold.literalType(value), value)
case SingletonTypeTree(ref) =>
val ref1 = checkStable(transform(ref, EXPRmode | QUALmode, AnyRefClass.tpe));
@@ -1079,7 +1083,7 @@ abstract class Typers: Analyzer {
if (tpt1.tpe.isError)
setError(tree)
else if (tparams.length == args1.length)
- tree setType appliedType(tpt1.tpe, args1 map (.tpe))
+ TypeTree() setPos tree.pos setType appliedType(tpt1.tpe, args1 map (.tpe))
else if (tparams.length == 0)
errorTree(tree, "" + tpt1.tpe + " does not take type parameters")
else
@@ -1089,8 +1093,10 @@ abstract class Typers: Analyzer {
def transform(tree: Tree, mode: int, pt: Type): Tree =
try {
- if (settings.debug.value) assert(pt != null, tree);//debug
- if (settings.debug.value) System.out.println("transforming " + tree);//debug
+ if (settings.debug.value) {
+ assert(pt != null, tree);//debug
+ //System.out.println("transforming " + tree);//DEBUG
+ }
val tree1 = if (tree.tpe != null) tree else transform1(tree, mode, pt);
if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt)
} catch {
@@ -1099,7 +1105,7 @@ abstract class Typers: Analyzer {
setError(tree)
case ex: Throwable =>
if (true || settings.debug.value)//!!!
- System.out.println("exception when tranforming " + tree + ", pt = " + pt);
+ System.out.println("exception when transforming " + tree + ", pt = " + pt);
throw(ex)
}