summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-07-21 16:17:35 +0000
committerMartin Odersky <odersky@gmail.com>2005-07-21 16:17:35 +0000
commitb23d885feb9c36007913caaf2104895212b33e1e (patch)
tree83964c7ebb5bf44ec00b7b2dc33cbcb0a1a2889d /sources/scala/tools/nsc
parent2b073f0a006c77eb847fc5cbe3c2421b5e64498e (diff)
downloadscala-b23d885feb9c36007913caaf2104895212b33e1e.tar.gz
scala-b23d885feb9c36007913caaf2104895212b33e1e.tar.bz2
scala-b23d885feb9c36007913caaf2104895212b33e1e.zip
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc')
-rwxr-xr-xsources/scala/tools/nsc/Global.scala129
-rw-r--r--sources/scala/tools/nsc/Phase.scala13
-rw-r--r--sources/scala/tools/nsc/Settings.scala2
-rw-r--r--sources/scala/tools/nsc/SubComponent.scala8
-rwxr-xr-xsources/scala/tools/nsc/ast/TreeGen.scala7
-rw-r--r--sources/scala/tools/nsc/ast/TreePrinters.scala6
-rw-r--r--sources/scala/tools/nsc/ast/Trees.scala4
-rw-r--r--sources/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala5
-rw-r--r--sources/scala/tools/nsc/ast/parser/TreeBuilder.scala2
-rw-r--r--sources/scala/tools/nsc/matching/PatternNodes.scala2
-rwxr-xr-xsources/scala/tools/nsc/symtab/Definitions.scala17
-rw-r--r--sources/scala/tools/nsc/symtab/Flags.scala13
-rwxr-xr-xsources/scala/tools/nsc/symtab/SymbolTable.scala2
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala39
-rwxr-xr-xsources/scala/tools/nsc/symtab/Types.scala190
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/Pickler.scala4
-rwxr-xr-xsources/scala/tools/nsc/transform/Erasure.scala434
-rwxr-xr-xsources/scala/tools/nsc/transform/InfoTransform.scala3
-rw-r--r--sources/scala/tools/nsc/transform/SampleTransform.scala2
-rw-r--r--sources/scala/tools/nsc/transform/TailCalls.scala4
-rw-r--r--sources/scala/tools/nsc/transform/Transform.scala7
-rwxr-xr-xsources/scala/tools/nsc/transform/UnCurry.scala10
-rw-r--r--sources/scala/tools/nsc/typechecker/Analyzer.scala22
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Namers.scala6
-rwxr-xr-xsources/scala/tools/nsc/typechecker/RefChecks.scala4
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala50
26 files changed, 725 insertions, 260 deletions
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala
index 90eeb3ffd7..06898a1297 100755
--- a/sources/scala/tools/nsc/Global.scala
+++ b/sources/scala/tools/nsc/Global.scala
@@ -16,7 +16,7 @@ import util._;
import ast._;
import ast.parser._;
import typechecker._;
-//import matching.TransMatcher;
+import matching.TransMatcher;
import transform._;
class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable with Trees with CompilationUnits {
@@ -121,10 +121,10 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
// Phases ------------------------------------------------------------
- abstract class StdPhase(prev: Phase) extends Phase(prev) {
+ abstract class GlobalPhase(prev: Phase) extends Phase(prev) {
def run: unit = units foreach applyPhase;
def apply(unit: CompilationUnit): unit;
- private val isErased = /*prev == erasurePhase ||*/ prev.erasedTypes;
+ private val isErased = prev.name == "erasure" || prev.erasedTypes;
override def erasedTypes: boolean = isErased;
def applyPhase(unit: CompilationUnit): unit = {
if (settings.debug.value) inform("[running phase " + name + " on " + unit + "]");
@@ -134,81 +134,82 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
object syntaxAnalyzer extends SyntaxAnalyzer {
val global: Global.this.type = Global.this
-
}
- val parserPhase = new syntaxAnalyzer.ParserPhase(NoPhase);
- val firstPhase = parserPhase;
- phase = parserPhase;
-
- definitions.init; // needs firstPhase to be defined, that's why it is placed here.
object analyzer extends Analyzer {
val global: Global.this.type = Global.this;
}
- val typer = new analyzer.Typer(analyzer.NoContext.make(EmptyTree, definitions.RootClass, new Scope())) {
- override def typed(tree: Tree, mode: int, pt: Type): Tree = {
- if (settings.debug.value) log("typing [[" + tree + "]]");
- val result = super.typed(tree, mode, pt);
- if (settings.debug.value) log(" ==> " + result + ":" + result.tpe);
- result
- }
- }
- val infer = typer.infer;
-
- val namerPhase = new analyzer.NamerPhase(parserPhase);
- val typerPhase = new analyzer.TyperPhase(namerPhase);
object pickler extends Pickler {
val global: Global.this.type = Global.this
}
- val picklePhase = new pickler.PicklePhase(typerPhase);
object refchecks extends RefChecks {
val global: Global.this.type = Global.this;
}
- val refchecksPhase = new refchecks.Phase(picklePhase);
object uncurry extends UnCurry {
val global: Global.this.type = Global.this;
}
- val uncurryPhase = new uncurry.Phase(refchecksPhase);
object tailCalls extends TailCalls {
val global: Global.this.type = Global.this;
}
- val tailCallPhase = new tailCalls.Phase(uncurryPhase);
-/*
- object transmatcher extends TransMatcher {
+ object transMatcher extends TransMatcher {
+ val global: Global.this.type = Global.this;
+ }
+ object erasure extends Erasure {
val global: Global.this.type = Global.this;
}
- val transMatchPhase = new transmatcher.Phase(tailCallPhase);
-*/
object sampleTransform extends SampleTransform {
val global: Global.this.type = Global.this;
}
- val samplePhase = new sampleTransform.Phase(tailCallPhase);
-
- //val transMatchPhase = new transmatcher.TransMatchPhase(picklePhase);
-/*
- object icode extends ICode {
- val symtab: Global.this.type = Global.this
+ def phaseDescriptors: List[SubComponent] = List(
+ analyzer.namerFactory, // needs to be first
+ analyzer.typerFactory, // needs to be second
+ pickler,
+ refchecks,
+ uncurry,
+ tailCalls,
+ transMatcher,
+ erasure,
+ sampleTransform);
+
+ val parserPhase = syntaxAnalyzer.newPhase(NoPhase);
+ val firstPhase = parserPhase;
+ phase = parserPhase;
+ definitions.init; // needs firstPhase and phase to be defined != NoPhase,
+ // that's why it is placed here.
+
+ private var p = phase;
+ private var stopped = false;
+ for (val pd <- phaseDescriptors) {
+ if (!stopped) {
+ if (!(settings.skip contains pd.phaseName)) p = pd.newPhase(p);
+ stopped = settings.stop contains pd.phaseName;
+ }
}
- val codegenPhase = new icode.CodeGenPhase(erasurePhase)
-
- abstract class CodeGenPhase(prev: Phase) extends StdPhase(prev) {
- import global._;
- ...
- }
-*/
- val terminalPhase = new Phase(samplePhase) {
+ val terminalPhase = new GlobalPhase(p) {
def name = "terminal";
- def run: unit = {}
+ def apply(unit: CompilationUnit): unit = {}
}
+ val namerPhase = parserPhase.next;
+ val typerPhase = namerPhase.next;
+
+ val typer = new analyzer.Typer(analyzer.NoContext.make(EmptyTree, definitions.RootClass, new Scope())) {
+ override def typed(tree: Tree, mode: int, pt: Type): Tree = {
+ if (settings.debug.value) log("typing [[" + tree + "]]");
+ val result = super.typed(tree, mode, pt);
+ if (settings.debug.value) log(" ==> " + result + ":" + result.tpe);
+ result
+ }
+ }
+ val infer = typer.infer;
// Units and how to compile them -------------------------------------
@@ -242,14 +243,12 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
globalPhase = NoPhase.next;
while (globalPhase != terminalPhase && reporter.errors() == 0) {
- if (!(settings.skip contains globalPhase.name)) {
- val startTime = System.currentTimeMillis();
- phase = globalPhase;
- globalPhase.run;
- if (settings.print contains globalPhase.name) treePrinter.printAll();
- informTime(globalPhase.description, startTime);
- }
- globalPhase = if (settings.stop contains globalPhase.name) terminalPhase else globalPhase.next;
+ val startTime = System.currentTimeMillis();
+ phase = globalPhase;
+ globalPhase.run;
+ if (settings.print contains globalPhase.name) treePrinter.printAll();
+ informTime(globalPhase.description, startTime);
+ globalPhase = globalPhase.next;
if (settings.check contains globalPhase.name) {
phase = globalPhase;
checker.checkTrees;
@@ -283,11 +282,10 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
else if (!(fileset contains file)) {
val unit = new CompilationUnit(getSourceFile(file));
addUnit(unit);
- var localPhase = parserPhase.asInstanceOf[StdPhase];
- while (localPhase.id < globalPhase.id || localPhase.id <= namerPhase.id) {
- if (!(settings.skip contains localPhase.name))
- atPhase(localPhase)(localPhase.applyPhase(unit));
- localPhase = localPhase.next.asInstanceOf[StdPhase];
+ var localPhase = parserPhase.asInstanceOf[GlobalPhase];
+ while (localPhase.id < globalPhase.id || localPhase.id <= parserPhase.next.id) {
+ atPhase(localPhase)(localPhase.applyPhase(unit));
+ localPhase = localPhase.next.asInstanceOf[GlobalPhase];
}
}
@@ -361,22 +359,5 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
inform("#typecreates : " + accesses);
inform("#uniquetypes : " + uniques);
inform("#collisions : " + collisions);
-/*
- inform("#uniqueThis : " + uniqueThis) ;
- inform("#uniqueSingle : " + uniqueSingle) ;
- inform("#uniqueSuper : " + uniqueSuper) ;
- inform("#uniqueTypeRef : " + uniqueTypeRef) ;
- inform("#uniqueTypeBounds : " + uniqueTypeBounds) ;
- inform("#uniqueConstant : " + uniqueConstant) ;
- inform("#uniqueMethod : " + uniqueMethod) ;
- inform("#duplicateThis : " + duplicateThis) ;
- inform("#duplicateSingle : " + duplicateSingle) ;
- inform("#duplicateSuper : " + duplicateSuper) ;
- inform("#duplicateTypeRef : " + duplicateTypeRef) ;
- inform("#duplicateTypeBounds : " + duplicateTypeBounds) ;
- inform("#duplicateConstant : " + duplicateConstant) ;
- inform("#duplicateMethod : " + duplicateMethod) ;
-*/
- //for (val tp <- allTypes) System.out.println("unique: " + tp)
}
}
diff --git a/sources/scala/tools/nsc/Phase.scala b/sources/scala/tools/nsc/Phase.scala
index d344e8486a..9fd2322845 100644
--- a/sources/scala/tools/nsc/Phase.scala
+++ b/sources/scala/tools/nsc/Phase.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc;
abstract class Phase(val prev: Phase) {
val id: int = if (prev == null) 0 else prev.id + 1;
- private var nx: Phase = NoPhase;
+ private var nx: Phase = this;
if (prev != null) prev.nx = this;
def next: Phase = nx;
@@ -20,17 +20,6 @@ abstract class Phase(val prev: Phase) {
def run: unit;
override def toString() = name;
-
- //commented out, just use `id' to compare.
- /*
- def >= (other: Phase): Boolean = {
- this == other || prev >= other
- }
- */
-
- // def check(units: List[CompilationUnit]): unit =
- // for (val unit <- units; val checker <- checkers) checker.traverse(unit); // def checkers: List[Checker] = List();
-
}
diff --git a/sources/scala/tools/nsc/Settings.scala b/sources/scala/tools/nsc/Settings.scala
index 88b05013dd..e9bb2cbea8 100644
--- a/sources/scala/tools/nsc/Settings.scala
+++ b/sources/scala/tools/nsc/Settings.scala
@@ -40,7 +40,7 @@ class Settings(error: String => unit) {
val printer = ChoiceSetting ("-printer", "Printer to use", List("text", "html"), "text");
val printfile = StringSetting ("-printfile", "file", "Specify file in which to print trees", "-");
val graph = PhasesSetting ("-graph", "Graph the program after");
- val stop = PhasesSetting ("-stop", "Stop after first phase in");
+ val stop = PhasesSetting ("-stop", "Stop after phase");
val log = PhasesSetting ("-log", "Log operations in");
val version = BooleanSetting("-version", "Print product version and exit");
val help = BooleanSetting("-help", "Print a synopsis of standard options");
diff --git a/sources/scala/tools/nsc/SubComponent.scala b/sources/scala/tools/nsc/SubComponent.scala
index 9bed9fc07e..680c3cda77 100644
--- a/sources/scala/tools/nsc/SubComponent.scala
+++ b/sources/scala/tools/nsc/SubComponent.scala
@@ -8,8 +8,10 @@ package scala.tools.nsc;
/** An nsc sub-component.
*/
abstract class SubComponent {
-
val global: Global;
-
+ val phaseName: String;
+ def newPhase(prev: Phase): Phase;
+ abstract class StdPhase(prev: Phase) extends global.GlobalPhase(prev) {
+ def name = phaseName;
+ }
}
-
diff --git a/sources/scala/tools/nsc/ast/TreeGen.scala b/sources/scala/tools/nsc/ast/TreeGen.scala
index fa0c7ab2e8..eadb2fe5bc 100755
--- a/sources/scala/tools/nsc/ast/TreeGen.scala
+++ b/sources/scala/tools/nsc/ast/TreeGen.scala
@@ -18,7 +18,7 @@ abstract class TreeGen {
/** Builds a reference to value whose type is given stable prefix.
*/
- def mkQualifier(stable: Type): Tree = stable match {
+ def mkQualifier(tpe: Type): Tree = tpe match {
case NoPrefix =>
EmptyTree
case ThisType(clazz) =>
@@ -31,6 +31,11 @@ abstract class TreeGen {
case _ =>
qual
}
+ case TypeRef(pre, sym, args) =>
+ assert(phase.erasedTypes);
+ (if (sym.isModuleClass && !sym.isRoot)
+ Select(mkQualifier(sym.owner.tpe), sym.sourceModule)
+ else This(sym)) setType sym.tpe
}
/** Builds a reference to given symbol with given stable prefix. */
diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala
index ea3c9616eb..3571d192e6 100644
--- a/sources/scala/tools/nsc/ast/TreePrinters.scala
+++ b/sources/scala/tools/nsc/ast/TreePrinters.scala
@@ -197,8 +197,8 @@ abstract class TreePrinters {
case Throw(expr) =>
print("throw "); print(expr)
- case New(init) =>
- print("new "); print(init)
+ case New(tpe) =>
+ print("new "); print(tpe)
case Typed(expr, tp) =>
print("("); print(expr); print(") : "); print(tp);
@@ -220,7 +220,7 @@ abstract class TreePrinters {
case Select(qualifier, name) =>
if (global.settings.debug.value || qualifier.symbol == null ||
- (!qualifier.symbol.isRoot && !qualifier.symbol.isEmptyPackageClass)) {
+ (!qualifier.symbol.isRoot && !qualifier.symbol.isEmptyPackage)) {
print(qualifier); print(".");
}
print(symName(tree, name))
diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala
index 6f1c0452de..4577110125 100644
--- a/sources/scala/tools/nsc/ast/Trees.scala
+++ b/sources/scala/tools/nsc/ast/Trees.scala
@@ -330,7 +330,9 @@ abstract class Trees: Global {
* one should always use factory method below to build a user level new.
*/
case class New(tpt: Tree)
- extends TermTree;
+ extends TermTree {
+ assert(tpt.isType)
+ }
/** Factory method for object creation <new tpt(args_1)...(args_n)> */
def New(tpt: Tree, argss: List[List[Tree]]): Tree = {
diff --git a/sources/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/sources/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
index c0e06262dc..5609cee6bd 100644
--- a/sources/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
+++ b/sources/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
@@ -8,8 +8,9 @@ package scala.tools.nsc.ast.parser;
/** An nsc sub-component.
*/
abstract class SyntaxAnalyzer extends SubComponent with Parsers with Scanners {
- class ParserPhase(prev: scala.tools.nsc.Phase) extends global.StdPhase(prev) {
- def name = "parser";
+ val phaseName = "parser";
+ def newPhase(prev: Phase): StdPhase = new ParserPhase(prev);
+ class ParserPhase(prev: scala.tools.nsc.Phase) extends StdPhase(prev) {
def apply(unit: global.CompilationUnit): unit = {
global.informProgress("parsing " + unit);
unit.body = new Parser(unit).parse();
diff --git a/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala b/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 751bf04060..47648f339c 100644
--- a/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -94,7 +94,7 @@ abstract class TreeBuilder {
if (parents.tail.isEmpty && stats.isEmpty)
New(parents.head, argss)
else {
- val x = freshName(nme.ANON_CLASS_NAME.toString());
+ val x = freshName(nme.ANON_CLASS_NAME.toString()).toTypeName;
Block(
List(ClassDef(
FINAL | SYNTHETIC, x, List(), TypeTree(),
diff --git a/sources/scala/tools/nsc/matching/PatternNodes.scala b/sources/scala/tools/nsc/matching/PatternNodes.scala
index 9be79f1b0a..82ee9efd5d 100644
--- a/sources/scala/tools/nsc/matching/PatternNodes.scala
+++ b/sources/scala/tools/nsc/matching/PatternNodes.scala
@@ -336,7 +336,7 @@ trait PatternNodes: TransMatcher {
this.boundVars = newVars;
}
//sym.setInfo(tpe);
- sym.setType(tpe);
+ sym.setInfo(tpe);
this.boundVars(numVars) = ValDef(sym, init.duplicate);
numVars = numVars + 1;
}
diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala
index 1c41acfe1d..a620ec8190 100755
--- a/sources/scala/tools/nsc/symtab/Definitions.scala
+++ b/sources/scala/tools/nsc/symtab/Definitions.scala
@@ -135,6 +135,12 @@ abstract class Definitions: SymbolTable {
var Object_eq : Symbol = _;
var Object_ne : Symbol = _;
var Object_synchronized: Symbol = _;
+ var Object_isInstanceOf: Symbol = _;
+ var Object_asInstanceOf: Symbol = _;
+ def Object_equals = getMember(ObjectClass, nme.equals_);
+ def Object_hashCode = getMember(ObjectClass, nme.hashCode_);
+ def Object_toString = getMember(ObjectClass, nme.toString_);
+
var String_+ : Symbol = _;
// members of class scala.Iterator
@@ -146,6 +152,8 @@ abstract class Definitions: SymbolTable {
// boxed classes
var BoxedArrayClass: Symbol = _;
+ var BoxedAnyArrayClass: Symbol = _;
+ var BoxedObjectArrayClass: Symbol = _;
var BoxedNumberClass: Symbol = _;
var BoxedUnitClass: Symbol = _;
var BoxedUnitModule: Symbol = _;
@@ -343,13 +351,20 @@ abstract class Definitions: SymbolTable {
ObjectClass, "ne", List(AnyRefClass.typeConstructor), BooleanClass.typeConstructor) setFlag FINAL;
Object_synchronized = newPolyMethod(
ObjectClass, "synchronized", tparam => MethodType(List(tparam.typeConstructor), tparam.typeConstructor)) setFlag FINAL;
-
+ Object_isInstanceOf = newPolyMethod(
+ ObjectClass, "$isInstanceOf",
+ tparam => MethodType(List(), BooleanClass.typeConstructor)) setFlag FINAL;
+ Object_asInstanceOf = newPolyMethod(
+ ObjectClass, "$asInstanceOf",
+ tparam => MethodType(List(), tparam.typeConstructor)) setFlag FINAL;
String_+ = newMethod(
StringClass, "+", List(AnyClass.typeConstructor), StringClass.typeConstructor) setFlag FINAL;
PatternWildcard = NoSymbol.newValue(Position.NOPOS, "_").setInfo(AllClass.typeConstructor);
BoxedArrayClass = getClass("scala.runtime.BoxedArray");
+ BoxedAnyArrayClass = getClass("scala.runtime.BoxedAnyArray");
+ BoxedObjectArrayClass = getClass("scala.runtime.BoxedObjectArray");
BoxedNumberClass = getClass("scala.runtime.BoxedNumber");
BoxedUnitClass = getClass("scala.runtime.BoxedUnit");
BoxedUnitModule = getModule("scala.runtime.BoxedUnit");
diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala
index 8823f3d49f..14c5febb3d 100644
--- a/sources/scala/tools/nsc/symtab/Flags.scala
+++ b/sources/scala/tools/nsc/symtab/Flags.scala
@@ -44,8 +44,7 @@ object Flags {
final val ACCESSED = 0x01000000; // symbol was accessed at least once
final val SELECTOR = 0x02000000; // symbol was used as selector in Select
-
- final val CAPTURED = 0x04000000; // variable is accessed from nested function. Set by LambdaLift
+ final val BRIDGE = 0x04000000; // function is a bridge method. Set by Erasure
final val ACCESSOR = 0x08000000; // a value or variable accessor
final val ACCESS_METHOD = 0x10000000; // function is an access function for a method in some
@@ -54,7 +53,7 @@ object Flags {
// for parameters: is a val parameter
final val LABEL = 0x40000000; // symbol is a label. Set by TailCall
- final val BRIDGE = 0x80000000; // function is a bridge method. Set by Erasure
+ final val CAPTURED = 0x80000000l; // variable is accessed from nested function. Set by LambdaLift
final val INTERFACE = 0x100000000l; // symbol is an interface
final val IS_ERROR = 0x200000000l; // symbol is an error symbol
@@ -94,10 +93,11 @@ object Flags {
.filter("" !=).mkString("", " ", "");
private def flagToString(flag: long): String = {
- if (flag == INTERFACE) "<interface>"
- else if (flag == IS_ERROR) "<is_error>"
+ if (flag == CAPTURED) "<captured>"
+ else if (flag == INTERFACE) "<interface>"
+ else if (flag == IS_ERROR) "<is-error>"
else if (flag == OVERLOADED) "<overloaded>"
- else if (flag == TRANS_FLAG) "<transient>"
+ else if (flag == TRANS_FLAG) "<trans-flag>"
else if (flag == INITIALIZED) "<initialized>"
else if (flag == LOCKED) "<locked>"
else flag.asInstanceOf[int] match {
@@ -133,7 +133,6 @@ object Flags {
case ACCESSED => "<accessed>"
case SELECTOR => "<selector>"
- case CAPTURED => "<captured>"
case ACCESSOR => "<accessor>"
case ACCESS_METHOD => "<access>"
diff --git a/sources/scala/tools/nsc/symtab/SymbolTable.scala b/sources/scala/tools/nsc/symtab/SymbolTable.scala
index 910886a9dd..afcebe2f7e 100755
--- a/sources/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/sources/scala/tools/nsc/symtab/SymbolTable.scala
@@ -24,7 +24,7 @@ abstract class SymbolTable extends Names
def phase: Phase = ph;
def phase_=(p: Phase): unit = {
//System.out.println("setting phase to " + p);
- assert(p != null);
+ assert(p != null && p != NoPhase);
ph = p
}
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
index 36f9f50869..e6f09c8888 100755
--- a/sources/scala/tools/nsc/symtab/Symbols.scala
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -233,6 +233,7 @@ abstract class Symbols: SymbolTable {
/** Set initial info. */
def setInfo(info: Type): this.type = {
+ if (name == newTypeName("Array") && info.isInstanceOf[PolyType]) assert(info.typeParams.length == 1, info);
if (limit == NoPhase) {
assert(phase != NoPhase);
infos = new TypeHistory(phase, info, null);
@@ -316,6 +317,7 @@ abstract class Symbols: SymbolTable {
resetFlags;
pos = Position.NOPOS;
infos = null;
+ limit = NoPhase;
setInfo(completer)
}
@@ -385,7 +387,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(flags);
+ cloneSymbolImpl(owner).setInfo(info.cloneInfo(owner)).setFlag(this.rawflags);
/** Internal method to clone a symbol's implementation without flags or type
*/
@@ -498,9 +500,11 @@ abstract class Symbols: SymbolTable {
final def tag: int = fullNameString.hashCode();
/** The simple name of this Symbol (this is always a term name) */
- final def simpleName: Name =
- if (isConstructor && !settings.debug.value) owner.name.toTermName else name;
-
+ final def simpleName: Name = name;
+/*
+ if (isConstructor && !settings.debug.value)
+ newTermName("<init owner.name.toTermName else name;
+*/
/** String representation of symbol's definition key word */
final def keyString: String =
if (isTrait)
@@ -645,7 +649,7 @@ abstract class Symbols: SymbolTable {
private var tpePhase: Phase = null;
override def tpe: Type = {
assert(tpeCache != NoType, this);
- if (tpePhase != phase)
+ if (tpePhase != phase) {
if (isValid(tpePhase)) tpePhase = phase
else {
if (hasFlag(INITIALIZED)) tpePhase = phase;
@@ -653,7 +657,8 @@ abstract class Symbols: SymbolTable {
tpeCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType,
this, unsafeTypeParams map (.tpe))
}
- assert(tpeCache != null/*, "" + this + " " + phase*/);//debug
+ }
+ assert(tpeCache != null/*, "" + this + " " + phase*/);//debug
tpeCache
}
override def typeConstructor: Type = {
@@ -678,8 +683,7 @@ abstract class Symbols: SymbolTable {
}
/** A class for class symbols */
- class ClassSymbol(initOwner: Symbol, initPos: int, initName: Name)
- extends TypeSymbol(initOwner, initPos, initName) {
+ class ClassSymbol(initOwner: Symbol, initPos: int, initName: Name) extends TypeSymbol(initOwner, initPos, initName) {
var sourceFile: AbstractFile = null;
private var thissym: Symbol = this;
override def isClass: boolean = true;
@@ -688,16 +692,21 @@ abstract class Symbols: SymbolTable {
thissym = this;
}
- private var thisTypeCache: Type = null;
+ private var thisTypeCache: Type = _;
+ private var thisTypePhase: Phase = null;
/** the type this.type in this class */
override def thisType: Type = {
- if (thisTypeCache == null) {
- thisTypeCache =
- if (isModuleClass && !isRoot) {
- assert(sourceModule != NoSymbol);
- singleType(owner.thisType, sourceModule);
- } else ThisType(this);
+ val p = thisTypePhase;
+ if (p != phase) {
+ thisTypePhase = phase;
+ if (!isValid(p)) {
+ thisTypeCache =
+ if (isModuleClass && !isRoot) {
+ assert(sourceModule != NoSymbol);
+ singleType(owner.thisType, sourceModule);
+ } else ThisType(this);
+ }
}
thisTypeCache
}
diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala
index 7a948a38a1..212142866f 100755
--- a/sources/scala/tools/nsc/symtab/Types.scala
+++ b/sources/scala/tools/nsc/symtab/Types.scala
@@ -57,7 +57,9 @@ abstract class Types: SymbolTable {
/** Map to a this type which is a subtype of this type.
*/
- def narrow: Type = refinedType(List(this), commonOwner(this), EmptyScope).narrow;
+ def narrow: Type =
+ if (phase.erasedTypes) this
+ else refinedType(List(this), commonOwner(this), EmptyScope).narrow;
/** Map a constant type to its underlying base type,
* identity for all other types */
@@ -374,7 +376,6 @@ abstract class Types: SymbolTable {
* to their immediate supertype
*/
abstract class SubType extends Type {
- assert(!phase.erasedTypes, this);
def supertype: Type;
override def parents: List[Type] = supertype.parents;
override def decls: Scope = supertype.decls;
@@ -804,34 +805,39 @@ abstract class Types: SymbolTable {
if (phase.erasedTypes)
sym.tpe
else if (checkMalformedSwitch && !pre.isStable && !pre.isError)
- throw new MalformedType(pre, sym.name.toString());
+ throw new MalformedType(pre, sym.name.toString())
else
unique(new SingleType(pre, rebind(pre, sym)) with UniqueType {})
}
/** The canonical creator for super-types */
def SuperType(thistp: Type, supertp: Type): Type =
- if (phase.erasedTypes) supertp else unique(new SuperType(thistp, supertp) with UniqueType {});
+ if (phase.erasedTypes) supertp
+ else unique(new SuperType(thistp, supertp) with UniqueType);
/** The canonical creator for type bounds */
def TypeBounds(lo: Type, hi: Type): TypeBounds =
- unique(new TypeBounds(lo, hi) with UniqueType {});
+ unique(new TypeBounds(lo, hi) with UniqueType);
/** the canonical creator for a refined type with a given scope */
- def refinedType(parents: List[Type], owner: Symbol, decls: Scope): RefinedType = {
- val clazz = owner.newRefinementClass(Position.NOPOS);
- val result = new RefinedType(parents, decls) { override def symbol: Symbol = clazz }
- clazz.setInfo(result);
- result
+ def refinedType(parents: List[Type], owner: Symbol, decls: Scope): Type = {
+ if (phase.erasedTypes)
+ if (parents.isEmpty) ObjectClass.tpe else parents.head
+ else {
+ val clazz = owner.newRefinementClass(Position.NOPOS);
+ val result = new RefinedType(parents, decls) { override def symbol: Symbol = clazz }
+ clazz.setInfo(result);
+ result
+ }
}
/** the canonical creator for a refined type with an initially empty scope */
- def refinedType(parents: List[Type], owner: Symbol): RefinedType =
+ def refinedType(parents: List[Type], owner: Symbol): Type =
refinedType(parents, owner, new Scope);
/** the canonical creator for a constant type */
def ConstantType(value: Constant): ConstantType =
- unique(new ConstantType(value) with UniqueType {});
+ unique(new ConstantType(value) with UniqueType);
/** The canonical creator for typerefs */
def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = {
@@ -854,14 +860,9 @@ abstract class Types: SymbolTable {
/** create a type-ref as found, without checks or rebinds */
def rawTypeRef(pre: Type, sym: Symbol, args: List[Type]): Type = {
- unique(new TypeRef(pre, sym, args) with UniqueType {})
+ unique(new TypeRef(pre, sym, args) with UniqueType)
}
- /** The canonical creator for method types
- def MethodType(paramTypes: List[Type], resultType: Type): MethodType =
- unique(new MethodType(paramTypes, resultType) with UniqueType {});
-*/
-
/** The canonical creator for implicit method types */
def ImplicitMethodType(paramTypes: List[Type], resultType: Type): ImplicitMethodType =
new ImplicitMethodType(paramTypes, resultType); // don't unique this!
@@ -1611,45 +1612,49 @@ abstract class Types: SymbolTable {
val lubParents = spanningTypes(List.fromArray(lubBaseTypes));
val lubOwner = commonOwner(ts);
val lubBase = intersectionType(lubParents, lubOwner);
- val lubType = refinedType(lubParents, lubOwner);
- val lubThisType = lubType.symbol.thisType;
- val narrowts = ts map (.narrow);
- def lubsym(proto: Symbol): Symbol = {
- val prototp = lubThisType.memberInfo(proto);
- val syms = narrowts map (t =>
- t.nonPrivateMember(proto.name).suchThat(sym =>
- sym.tpe matches prototp.substThis(lubThisType.symbol, t)));
- if (syms contains NoSymbol) NoSymbol
- else {
- val symtypes = List.map2(narrowts, syms)
+ if (phase.erasedTypes) lubBase
+ else {
+ val lubType = refinedType(lubParents, lubOwner);
+ val lubThisType = lubType.symbol.thisType;
+ val narrowts = ts map (.narrow);
+ def lubsym(proto: Symbol): Symbol = {
+ val prototp = lubThisType.memberInfo(proto);
+ val syms = narrowts map (t =>
+ t.nonPrivateMember(proto.name).suchThat(sym =>
+ sym.tpe matches prototp.substThis(lubThisType.symbol, t)));
+ if (syms contains NoSymbol) NoSymbol
+ else {
+ val symtypes = List.map2(narrowts, syms)
((t, sym) => t.memberInfo(sym).substThis(t.symbol, lubThisType));
- if (settings.debug.value) log("common symbols: " + syms + ":" + symtypes);//debug
- if (proto.isTerm)
- proto.cloneSymbol.setInfo(lub(symtypes))
- else if (symtypes.tail forall (symtypes.head =:=))
- proto.cloneSymbol.setInfo(symtypes.head)
- else {
- def lubBounds(bnds: List[TypeBounds]): TypeBounds =
- TypeBounds(glb(bnds map (.lo)), lub(bnds map (.hi)));
- proto.owner.newAbstractType(proto.pos, proto.name)
- .setInfo(lubBounds(symtypes map (.bounds)))
- }
- }
- }
- def refines(tp: Type, sym: Symbol): boolean = {
- val syms = tp.nonPrivateMember(sym.name).alternatives;
- !syms.isEmpty && (syms forall (alt =>
- // todo alt != sym is strictly speaking not correct, but without it we lose
- // efficiency.
- alt != sym && !specializesSym(lubThisType, sym, tp, alt)))
+ if (settings.debug.value) log("common symbols: " + syms + ":" + symtypes);//debug
+ if (proto.isTerm)
+ proto.cloneSymbol.setInfo(lub(symtypes))
+ else if (symtypes.tail forall (symtypes.head =:=))
+ proto.cloneSymbol.setInfo(symtypes.head)
+ else {
+ def lubBounds(bnds: List[TypeBounds]): TypeBounds =
+ TypeBounds(glb(bnds map (.lo)), lub(bnds map (.hi)));
+ proto.owner.newAbstractType(proto.pos, proto.name)
+ .setInfo(lubBounds(symtypes map (.bounds)))
+ }
+ }
+ }
+ def refines(tp: Type, sym: Symbol): boolean = {
+ val syms = tp.nonPrivateMember(sym.name).alternatives;
+ !syms.isEmpty && (syms forall (alt =>
+ // todo alt != sym is strictly speaking not correct, but without it we lose
+ // efficiency.
+ alt != sym && !specializesSym(lubThisType, sym, tp, alt)))
+ }
+ for (val sym <- lubBase.nonPrivateMembers)
+ // add a refinement symbol for all non-class members of lubBase
+ // which are refined by every type in ts.
+ if (!sym.isClass && !sym.isConstructor && (narrowts forall (t => refines(t, sym))))
+ addMember(lubThisType, lubType, lubsym(sym));
+ if (lubType.decls.isEmpty) lubBase else lubType;
}
- for (val sym <- lubBase.nonPrivateMembers)
- // add a refinement symbol for all non-class members of lubBase
- // which are refined by every type in ts.
- if (!sym.isClass && !sym.isConstructor && (narrowts forall (t => refines(t, sym))))
- addMember(lubThisType, lubType, lubsym(sym));
- if (lubType.decls.isEmpty) lubBase else lubType;
}
+
if (settings.debug.value) {
log(indent + "lub of " + ts);//debug
indent = indent + " ";
@@ -1680,44 +1685,47 @@ abstract class Types: SymbolTable {
try {
val glbOwner = commonOwner(ts);
val glbBase = intersectionType(ts, glbOwner);
- val glbType = refinedType(ts, glbOwner);
- val glbThisType = glbType.symbol.thisType;
- def glbsym(proto: Symbol): Symbol = {
- val prototp = glbThisType.memberInfo(proto);
- val syms = for (
- val t <- ts;
- val alt <- t.nonPrivateMember(proto.name).alternatives;
- glbThisType.memberInfo(alt) matches prototp) yield alt;
- val symtypes = syms map glbThisType.memberInfo;
- assert(!symtypes.isEmpty);
- proto.cloneSymbol.setInfo(
- if (proto.isTerm) glb(symtypes)
- else {
- def isTypeBound(tp: Type) = tp match {
- case TypeBounds(_, _) => true
- case _ => false
- }
- def glbBounds(bnds: List[Type]): TypeBounds = {
- val lo = lub(bnds map (.bounds.lo));
- val hi = glb(bnds map (.bounds.hi));
- if (lo <:< hi) TypeBounds(lo, hi)
- else throw new MalformedClosure(bnds)
- }
- val symbounds = symtypes filter isTypeBound;
- var result: Type =
- if (symbounds.isEmpty)
- TypeBounds(AllClass.tpe, AnyClass.tpe)
- else glbBounds(symbounds);
- for (val t <- symtypes; !isTypeBound(t))
- if (result.bounds containsType t) result = t
- else throw new MalformedClosure(symtypes);
- result
- })
+ if (phase.erasedTypes) glbBase
+ else {
+ val glbType = refinedType(ts, glbOwner);
+ val glbThisType = glbType.symbol.thisType;
+ def glbsym(proto: Symbol): Symbol = {
+ val prototp = glbThisType.memberInfo(proto);
+ val syms = for (
+ val t <- ts;
+ val alt <- t.nonPrivateMember(proto.name).alternatives;
+ glbThisType.memberInfo(alt) matches prototp) yield alt;
+ val symtypes = syms map glbThisType.memberInfo;
+ assert(!symtypes.isEmpty);
+ proto.cloneSymbol.setInfo(
+ if (proto.isTerm) glb(symtypes)
+ else {
+ def isTypeBound(tp: Type) = tp match {
+ case TypeBounds(_, _) => true
+ case _ => false
+ }
+ def glbBounds(bnds: List[Type]): TypeBounds = {
+ val lo = lub(bnds map (.bounds.lo));
+ val hi = glb(bnds map (.bounds.hi));
+ if (lo <:< hi) TypeBounds(lo, hi)
+ else throw new MalformedClosure(bnds)
+ }
+ val symbounds = symtypes filter isTypeBound;
+ var result: Type =
+ if (symbounds.isEmpty)
+ TypeBounds(AllClass.tpe, AnyClass.tpe)
+ else glbBounds(symbounds);
+ for (val t <- symtypes; !isTypeBound(t))
+ if (result.bounds containsType t) result = t
+ else throw new MalformedClosure(symtypes);
+ result
+ })
+ }
+ for (val t <- ts; val sym <- t.nonPrivateMembers)
+ if (!sym.isClass && !sym.isConstructor && !(glbThisType specializes sym))
+ addMember(glbThisType, glbType, glbsym(sym));
+ if (glbType.decls.isEmpty) glbBase else glbType
}
- for (val t <- ts; val sym <- t.nonPrivateMembers)
- if (!sym.isClass && !sym.isConstructor && !(glbThisType specializes sym))
- addMember(glbThisType, glbType, glbsym(sym));
- if (glbType.decls.isEmpty) glbBase else glbType;
} catch {
case _: MalformedClosure =>
if (ts forall (t => t <:< AnyRefClass.tpe)) AllRefClass.tpe
diff --git a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala
index 217c7521f6..8123fe6973 100755
--- a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -18,8 +18,10 @@ import PickleFormat._;
abstract class Pickler extends SubComponent {
import global._;
+ val phaseName = "pickler";
+ def newPhase(prev: Phase): StdPhase = new PicklePhase(prev);
+
class PicklePhase(prev: Phase) extends StdPhase(prev) {
- def name = "pickler";
def apply(unit: CompilationUnit): unit = {
def pickle(tree: Tree): unit = {
diff --git a/sources/scala/tools/nsc/transform/Erasure.scala b/sources/scala/tools/nsc/transform/Erasure.scala
new file mode 100755
index 0000000000..a04b8b31ea
--- /dev/null
+++ b/sources/scala/tools/nsc/transform/Erasure.scala
@@ -0,0 +1,434 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author
+ */
+// $Id$
+package scala.tools.nsc.transform;
+
+import collection.mutable.HashMap;
+import symtab._;
+import Flags._;
+import scala.tools.util.Position;
+import util.ListBuffer;
+
+abstract class Erasure extends InfoTransform with typechecker.Analyzer {
+ import global._; // the global environment
+ import definitions._; // standard classes and methods
+ import typer.{typed}; // methods to type trees
+ import posAssigner.atPos; // for filling in tree positions
+
+ val phaseName: String = "erasure";
+ def newTransformer(unit: CompilationUnit): Transformer = new ErasureTransformer(unit);
+
+// -------- erasure on types --------------------------------------------------------
+
+ /** The erasure |T| of a type T. This is:
+ * - For a constant type, itself.
+ * - For a type-bounds structure, the erasure of its upper bound.
+ * - For every other singleton type, the erasure of its supertype.
+ * - For a typeref scala.Array[T] where T is an abstract type, scala.runtime.BoxedArray.
+ * - For a typeref scala.Array[T] where T is not an abstract type, scala.Array[|T|].
+ * - For a typeref scala.Any or scala.AnyVal, java.lang.Object.
+ * - For a typeref scala.Unit, scala.runtime.BoxedUnit.
+ * - For a typeref P.C[Ts] where C refers to a class, |P|.C.
+ * - For a typeref P.C[Ts] where C refers to an alias type, the erasure of C's alias.
+ * - For a typeref P.C[Ts] where C refers to an abstract type, the erasure of C's upper bound.
+ * - For a non-empty type intersection (possibly with refinement), the erasure of its first parent.
+ * - For an empty type intersection, java.lang.Object
+ * - For a method type (Fs)scala.Unit, (|Fs|)scala#Unit.
+ * - For any other method type (Fs)Y, (|Fs|)|T|.
+ * - For a polymorphic type, the erasure of its result type
+ * - For the class info type of java.lang.Object, the same type without any parents
+ * - For a class info type of a value class, the same type without any parents
+ * - For any other class info type with parents Ps, the same type with parents |Ps}, but
+ * with duplicate references of Object removed.
+ * - for all other types, the type itself (with any sub-components erased)
+ */
+ private val erasure = new TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case ConstantType(value) =>
+ tp
+ case st: SubType =>
+ apply(st.supertype)
+ case TypeRef(pre, sym, args) =>
+ if (sym == ArrayClass)
+ args.head match {
+ case TypeRef(_, tvar, _) if (tvar.isAbstractType) => erasedTypeRef(BoxedArrayClass)
+ case _ => typeRef(apply(pre), sym, args map this)
+ }
+ else if (sym == AnyClass || sym == AnyValClass) erasedTypeRef(ObjectClass)
+ else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass)
+ else if (sym.isClass) typeRef(apply(pre), sym, List())
+ else apply(sym.info)
+ case PolyType(tparams, restpe) =>
+ apply(restpe)
+ case MethodType(formals, restpe) =>
+ MethodType(
+ formals map apply,
+ if (restpe.symbol == UnitClass) erasedTypeRef(UnitClass) else apply(restpe));
+ case RefinedType(parents, decls) =>
+ if (parents.isEmpty) erasedTypeRef(ObjectClass)
+ else apply(parents.head)
+ case ClassInfoType(parents, decls, clazz) =>
+ ClassInfoType(
+ if ((clazz == ObjectClass) || (isValueClass(clazz))) List()
+ else if (clazz == ArrayClass) List(erasedTypeRef(ObjectClass))
+ else removeDoubleObject(parents map this),
+ decls, clazz)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ /** Type reference after erasure */
+ private def erasedTypeRef(sym: Symbol): Type = typeRef(erasure(sym.owner.tpe), sym, List());
+
+ /** Remove duplicate references to class Object in a list of parent classes
+ */
+ private def removeDoubleObject(tps: List[Type]): List[Type] = tps match {
+ case List() => List()
+ case tp :: tps1 =>
+ if (tp.symbol == ObjectClass) tp :: tps1.filter(.symbol.!=(ObjectClass))
+ else tp :: removeDoubleObject(tps1)
+ }
+
+ /** The symbol's erased info. This is the type's erasure, except for the following symbols
+ * - For $asInstanceOf : [T]T
+ * - For $isInstanceOf : [T]scala#Boolean
+ * - For class Array : [T]C where C is the erased classinfo of the Array class
+ * - For the Array[T].<init>: {scala#Int)Array[T]
+ * - For a type parameter : A type bounds type consisting of the erasures of its bounds.
+ */
+ def transformInfo(sym: Symbol, tp: Type): Type =
+ if (sym == Object_asInstanceOf)
+ sym.info
+ else if (sym == Object_isInstanceOf || sym == ArrayClass)
+ PolyType(sym.info.typeParams, erasure(sym.info.resultType))
+ else if (sym.name == nme.CONSTRUCTOR && sym.owner == ArrayClass)
+ tp match {
+ case MethodType(formals, TypeRef(pre, sym, args)) =>
+ MethodType(formals map erasure, typeRef(erasure(pre), sym, args))
+ }
+ else if (sym.isAbstractType)
+ erasure.mapOver(tp)
+ else
+ erasure(tp);
+
+// -------- boxing/unboxing --------------------------------------------------------
+
+ override def newTyper(context: Context) = new Eraser(context);
+
+ /** The modifier typer which retypes with erased types. */
+ class Eraser(context: Context) extends Typer(context) {
+
+ /** Box `tree' of unboxed type */
+ private def box(tree: Tree): Tree =
+ typed {
+ atPos(tree.pos) {
+ val sym = tree.tpe.symbol;
+ if (sym == UnitClass) {
+ gen.mkRef(BoxedUnit_UNIT)
+ } else if (sym == ArrayClass) {
+ val elemClass = tree.tpe.typeArgs.head.symbol;
+ val boxedClass = if (isValueClass(elemClass)) boxedArraySym(elemClass)
+ else BoxedObjectArrayClass;
+ Apply(Select(New(TypeTree(boxedClass.tpe)), nme.CONSTRUCTOR), List(tree))
+ } else {
+ val boxedModule = boxedSym(tree.tpe.symbol).linkedModule;
+ Apply(Select(gen.mkRef(boxedModule), nme.box), List(tree))
+ }
+ }
+ }
+
+ /** Unbox `tree' of boxed type to expected type `pt' */
+ private def unbox(tree: Tree, pt: Type): Tree =
+ typed {
+ atPos(tree.pos) {
+ if (pt.symbol == UnitClass) {
+ Literal(())
+ } else if (pt.symbol == BooleanClass) {
+ val tree1 = adaptToType(tree, boxedSym(BooleanClass).tpe);
+ Apply(Select(tree1, "booleanValue"), List())
+ } else if (pt.symbol == ArrayClass) {
+ val tree1 = adaptToType(tree, BoxedArrayClass.tpe);
+ val elemClass = pt.typeArgs.head.symbol;
+ val elemTag =
+ if (isValueClass(elemClass))
+ Apply(
+ Select(gen.mkRef(ScalaRunTimeModule), newTermName(elemClass.name.toString() + "Tag")),
+ List())
+ else Literal(signature(pt));
+ Apply(Select(tree1, "unbox"), List(elemTag))
+ } else {
+ val tree1 = adaptToType(tree, BoxedNumberClass.tpe);
+ val unboxedName = pt.symbol.name.toString();
+ val unboxOp =
+ String.valueOf((unboxedName.charAt(0) + ('a' - 'A')).asInstanceOf[char]) +
+ unboxedName.substring(1) + "Value";
+ Apply(Select(tree1, unboxOp), List())
+ }
+ }
+ }
+
+ /** Cast `tree' to type `pt' */
+ private def cast(tree: Tree, pt: Type): Tree = {
+ if (settings.debug.value) log("casting " + tree + " to " + pt);
+ typed {
+ atPos(tree.pos) {
+ Apply(TypeApply(Select(tree, Object_asInstanceOf), List(TypeTree(pt))), List())
+ }
+ }
+ }
+
+ /** Is symbol a member of unboxed arrays (which will be expanded directly later)? */
+ private def isUnboxedArrayMember(sym: Symbol) =
+ sym.name == nme.apply || sym.name == nme.length || sym.name == nme.update ||
+ sym.owner == ObjectClass;
+
+ /** Is symbol a member of a boxed value class (which will not be expanded later)? */
+ def isBoxedValueMember(sym: Symbol) =
+ (sym.name == nme.equals_ || sym.name == nme.hashCode_ || sym.name == nme.toString_ ||
+ (sym.name == nme.EQ || sym.name == nme.NE) && sym.info.paramTypes.head.symbol == ObjectClass ||
+ sym == Object_isInstanceOf || sym == Object_asInstanceOf);
+
+ /** Adapt `tree' to expected type `pt' */
+ private def adaptToType(tree: Tree, pt: Type): Tree = {
+ if (settings.debug.value && pt != WildcardType) log("adapting " + tree + ":" + tree.tpe + " to " + pt);
+ if (tree.tpe <:< pt)
+ tree
+ else if (isUnboxedClass(tree.tpe.symbol) && !isUnboxedClass(pt.symbol))
+ adaptToType(box(tree), pt)
+ else if (pt <:< tree.tpe)
+ cast(tree, pt)
+ else if (isUnboxedClass(pt.symbol) && !isUnboxedClass(tree.tpe.symbol))
+ adaptToType(unbox(tree, pt), pt)
+ else
+ cast(tree, pt)
+ }
+
+
+ /** Replace member references as follows:
+ * - `x == y' for `==' in class Any becomes `x equals y' with `equals' in class Object
+ * - `x != y' for `!=' in class Any becomes `!(x equals y)' with `equals' in class Object
+ * - `new BoxedArray.<init>(len)' becomes `new BoxedAnyArray.<init>(len): BoxedArray'
+ * (the widening typing is necessary so that subsequent member symbols stay the same)
+ * - `x.asInstanceOf[T]' and `x.asInstanceOf$erased[T]' become `x.$asInstanceOf[T]'
+ * - `x.isInstanceOf[T]' and `x.isInstanceOf$erased[T]' become `x.$isInstanceOf[T]'
+ * - `x.m' where `m' is some other member of Any becomes `x.m' where m is a member of class Object
+ * - `x.m' where `x' has unboxed value type `T' and `m' is not a directly
+ * translated member of `T' becomes T.box(x).m
+ * - `x.m' where `x' has type `Array[T]' and `m' is not a directly
+ * translated member of `Array' becomes new BoxedTArray.<init>(x).m
+ * - `x.m' where `x' is a reference type and `m' is a directly translated member of value type
+ * T becomes x.TValue().m
+ * - All forms of `x.m' where `x' is a boxed type and `m' is a member of an unboxed class
+ * become `x.m' where `m' is the corresponding member of the boxed class.
+ */
+ private def adaptMember(tree: Tree): Tree = tree match {
+ case Apply(sel @ Select(qual, name), args) =>
+ if (sel.symbol == Any_==)
+ Apply(Select(qual, Object_equals), args)
+ else if (sel.symbol == Any_!=)
+ Apply(Select(Apply(Select(qual, Object_equals), args), Boolean_not), List())
+ else qual match {
+ case New(tpt) =>
+ assert(tpt.isInstanceOf[TypeTree]);
+ if (tpt.tpe.symbol == BoxedArrayClass) {
+ assert(name == nme.CONSTRUCTOR);
+ Typed(Apply(Select(New(TypeTree(BoxedAnyArrayClass.tpe)), name), args), tpt)
+ } else tree
+ case _ =>
+ tree
+ }
+ case Select(qual, name) if (name != nme.CONSTRUCTOR) =>
+ if (tree.symbol == Any_asInstanceOf || tree.symbol == Any_asInstanceOfErased)
+ adaptMember(Select(qual, Object_asInstanceOf))
+ else if (tree.symbol == Any_isInstanceOf || tree.symbol == Any_isInstanceOfErased)
+ adaptMember(Select(qual, Object_isInstanceOf))
+ else if (tree.symbol != NoSymbol && tree.symbol.owner == AnyClass)
+ adaptMember(Select(qual, getMember(ObjectClass, name)))
+ else {
+ var qual1 = typedQualifier(qual);
+ if ((isValueClass(qual1.tpe.symbol) && isBoxedValueMember(tree.symbol)) ||
+ (qual1.tpe.symbol == ArrayClass && !isUnboxedArrayMember(tree.symbol))) {
+ qual1 = box(qual1);
+ } else if (!isValueClass(qual1.tpe.symbol) &&
+ tree.symbol != NoSymbol && isValueClass(tree.symbol.owner)) {
+ qual1 = unbox(qual1, tree.symbol.owner.tpe)
+ }
+ if (tree.symbol != NoSymbol &&
+ isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.symbol))
+ tree.symbol = NoSymbol;
+ copy.Select(tree, qual1, name)
+ }
+ case _ =>
+ tree
+ }
+
+ /** A replacement for the standard typer's `adapt' method */
+ override protected def adapt(tree: Tree, mode: int, pt: Type): Tree = adaptToType(tree, pt);
+
+ /** A replacement for the standard typer's `typed1' method */
+ override protected def typed1(tree: Tree, mode: int, pt: Type): Tree =
+ super.typed1(adaptMember(tree), mode, pt);
+ }
+
+ /** The erasure transformer */
+ class ErasureTransformer(unit: CompilationUnit) extends Transformer {
+
+ /** Emit an error if there is a double definition. This can happen in the following
+ * circumstances:
+ * - A template defines two members with the same name and erased type.
+ * - A template defines and inherits two members `m' with different types,
+ * but their erased types are the same.
+ * - A template inherits two members `m' with different types,
+ * but their erased types are the same.
+ */
+ private def checkNoDoubleDefs(root: Symbol): unit = atPhase(phase.next) {
+ def doubleDefError(sym1: Symbol, sym2: Symbol) = {
+ val tpe1 = atPhase(typerPhase.next)(root.tpe.memberType(sym1));
+ val tpe2 = atPhase(typerPhase.next)(root.tpe.memberType(sym2));
+ unit.error(
+ if (sym1.owner == root) sym1.pos else root.pos,
+ (if (sym1.owner == sym2.owner) "double definition:\n"
+ else if (sym1.owner == root) "name clash between defined and inherited member:\n"
+ else "name clash between inherited members:\n") +
+ sym1 + ":" + tpe1 +
+ (if (sym1.owner == root) "" else sym1.locationString) + " and\n" +
+ sym2 + ":" + tpe2 +
+ (if (sym2.owner == root) " at line " + Position.line(sym2.pos) else sym2.locationString) +
+ "\nhave same type" +
+ (if (tpe1 =:= tpe2) "" else " after erasure: " + sym1.tpe))
+ }
+
+ val decls = root.info.decls;
+ var e = decls.elems;
+ while (e != null) {
+ if (e.sym.isTerm && !e.sym.isConstructor) {
+ var e1 = decls.lookupNextEntry(e);
+ while (e1 != null) {
+ if (e1.sym.info =:= e.sym.info) doubleDefError(e.sym, e1.sym);
+ e1 = decls.lookupNextEntry(e1)
+ }
+ }
+ e = e.next
+ }
+
+ for (val bc <- root.info.baseClasses.tail; val other <- bc.info.decls.toList) {
+ if (other.isTerm && !other.isConstructor && !(other hasFlag PRIVATE)) {
+ for (val member <- root.info.nonPrivateMember(other.name).alternatives) {
+ if (member != other && (member.tpe =:= other.tpe) &&
+ !atPhase(typerPhase.next)(
+ root.tpe.memberType(member) =:= root.tpe.memberType(other)))
+ doubleDefError(member, other)
+ }
+ }
+ }
+ }
+
+ /** Add bridge definitions to a template. This means:
+ * If there is a concrete member `m' which overrides a member in a base class of the template,
+ * and the erased types of the two members differ,
+ * and the two members are not inherited or defined by some parent class of the template,
+ * then a bridge from the overridden member `m1' to the member `m0' is added.
+ * The bridge has the erased type of `m1' and forwards to `m0'.
+ * No bridge is added if there is already a bridge to `m0' with the erased type of `m1'
+ * in the template.
+ */
+ private def bridgeDefs(owner: Symbol): List[Tree] = {
+ val site = owner.tpe;
+ val bridgesScope = new Scope();
+ val bridgeTarget = new HashMap[Symbol, Symbol];
+ var bridges: List[Tree] = List();
+ for (val bc <- site.baseClasses.tail; val other <- bc.info.members) {
+ if (other.isMethod && !other.isConstructor) {
+ for (val member <- site.nonPrivateMember(other.name).alternatives) {
+ if (member != other &&
+ !(member hasFlag DEFERRED) &&
+ (site.memberType(member) matches site.memberType(other)) &&
+ !(site.parents exists (p =>
+ (p.symbol isSubClass member.owner) && (p.symbol isSubClass other.owner)))) {
+ val otpe = erasure(other.tpe);
+ if (!(otpe =:= erasure(member.tpe))) {
+ var e = bridgesScope.lookupEntry(member.name);
+ while (e != null && !((e.sym.tpe =:= otpe) && (bridgeTarget(e.sym) == member)))
+ e = bridgesScope.lookupNextEntry(e);
+ if (e == null) {
+ val bridge = other.cloneSymbol(owner).setInfo(otpe).setFlag(BRIDGE);
+ if (settings.debug.value)
+ log("generating bridge from " + other + ":" + otpe + other.locationString + " to " + member + ":" + erasure(member.tpe) + "=" + bridge + ":" + bridge.tpe);
+ bridgeTarget(bridge) = member;
+ bridgesScope enter bridge;
+ bridges =
+ atPos(bridge.pos) {
+ DefDef(bridge, vparamss =>
+ ((Select(This(owner), bridgeTarget(bridge)): Tree) /: vparamss)
+ ((fun, vparams) => Apply(fun, vparams map Ident)))
+ } :: bridges;
+ }
+ }
+ }
+ }
+ }
+ }
+ bridges
+ }
+
+ /** Transform tree at phase `erasure' before retyping it. This entails the following:
+ * - Remove all type parameters in class and method definitions.
+ * - Remove all abstract and alias type definitions.
+ * - Remove all type applications other than those involving a type test or cast.
+ * - Remove all empty trees in statements and definitions in a PackageDef.
+ * - Check that there are no double definitions in a template.
+ * - Add bridge definitions to a template.
+ * - Replace all types in type nodes and the EmptyTree object by their erasure.
+ * Type nodes of type Unit representing result types of methods are left alone.
+ * - Reset all other type attributes to `null, thus enforcing a retyping.
+ */
+ private val preTransformer = new Transformer {
+ def elimEmpty(trees: List[Tree]): List[Tree] = trees filter (EmptyTree !=);
+ override def transform(tree: Tree): Tree = {
+ val tree1 = tree match {
+ case ClassDef(mods, name, tparams, tpt, impl) =>
+ copy.ClassDef(tree, mods, name, List(), tpt, impl)
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ copy.DefDef(tree, mods, name, List(), vparamss, tpt, rhs)
+ case AbsTypeDef(_, _, _, _) =>
+ EmptyTree
+ case AliasTypeDef(_, _, _, _) =>
+ EmptyTree
+ case TypeApply(fun, args) if (fun.symbol.owner != AnyClass) =>
+ // leave type tests/type casts, remove all other type applications
+ fun
+ case PackageDef(name, stats) =>
+ copy.PackageDef(tree, name, elimEmpty(stats))
+ case Template(parents, body) =>
+ checkNoDoubleDefs(tree.symbol.owner);
+ copy.Template(tree, parents, elimEmpty(body) ::: bridgeDefs(currentOwner))
+ case Block(stats, expr) =>
+ copy.Block(tree, elimEmpty(stats), expr)
+ case _ =>
+ tree
+ }
+ tree1 match {
+ case EmptyTree | TypeTree() =>
+ tree1 setType erasure(tree1.tpe)
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ val result = super.transform(tree1) setType null;
+ tpt.tpe = erasure(tree.symbol.tpe).resultType;
+ result
+ case _ =>
+ super.transform(tree1) setType null
+ }
+ }
+ }
+
+ /** The main transform function: Pretransfom the tree, and then
+ * re-type it at phase erasure.next.
+ */
+ override def transform(tree: Tree): Tree = {
+ val tree1 = preTransformer.transform(tree);
+ atPhase(phase.next) { newTyper(startContext).typed(tree1) }
+ }
+ }
+}
diff --git a/sources/scala/tools/nsc/transform/InfoTransform.scala b/sources/scala/tools/nsc/transform/InfoTransform.scala
index 8026019d88..c6d2997c65 100755
--- a/sources/scala/tools/nsc/transform/InfoTransform.scala
+++ b/sources/scala/tools/nsc/transform/InfoTransform.scala
@@ -9,11 +9,12 @@ package scala.tools.nsc.transform;
* A transform contains a compiler phase which applies a tree transformer.
*/
abstract class InfoTransform extends Transform {
-
import global.{Symbol, Type, InfoTransformer, infoTransformers};
def transformInfo(sym: Symbol, tpe: Type): Type;
+ override def newPhase(prev: scala.tools.nsc.Phase): StdPhase = new Phase(prev);
+
class Phase(prev: scala.tools.nsc.Phase) extends super.Phase(prev) {
val infoTransformer = new InfoTransformer {
val phase = Phase.this;
diff --git a/sources/scala/tools/nsc/transform/SampleTransform.scala b/sources/scala/tools/nsc/transform/SampleTransform.scala
index 7a525022c9..404e03e572 100644
--- a/sources/scala/tools/nsc/transform/SampleTransform.scala
+++ b/sources/scala/tools/nsc/transform/SampleTransform.scala
@@ -16,7 +16,7 @@ abstract class SampleTransform extends Transform {
import posAssigner.atPos; // for filling in tree positions
/** the following two members override abstract members in Transform */
- protected val phaseName: String = "sample-phase";
+ val phaseName: String = "sample-phase";
protected def newTransformer(unit: CompilationUnit): Transformer = new SampleTransformer(unit);
class SampleTransformer(unit: CompilationUnit) extends Transformer {
diff --git a/sources/scala/tools/nsc/transform/TailCalls.scala b/sources/scala/tools/nsc/transform/TailCalls.scala
index d34bc19047..d6836d1a5c 100644
--- a/sources/scala/tools/nsc/transform/TailCalls.scala
+++ b/sources/scala/tools/nsc/transform/TailCalls.scala
@@ -16,8 +16,8 @@ abstract class TailCalls extends Transform
import typer.{typed, atOwner}; // methods to type trees
import posAssigner.atPos; // for filling in tree positions
- protected val phaseName: String = "tailcalls";
- protected def newTransformer(unit: CompilationUnit): Transformer = new TailCallElimination(unit);
+ val phaseName: String = "tailcalls";
+ def newTransformer(unit: CompilationUnit): Transformer = new TailCallElimination(unit);
/**
* A Tail Call Transformer
diff --git a/sources/scala/tools/nsc/transform/Transform.scala b/sources/scala/tools/nsc/transform/Transform.scala
index cedc32118c..912800f0c3 100644
--- a/sources/scala/tools/nsc/transform/Transform.scala
+++ b/sources/scala/tools/nsc/transform/Transform.scala
@@ -9,12 +9,9 @@ package scala.tools.nsc.transform;
* A transform contains a compiler phase which applies a tree transformer.
*/
abstract class Transform extends SubComponent {
-
- protected val phaseName: String;
protected def newTransformer(unit: global.CompilationUnit): global.Transformer;
-
- class Phase(prev: scala.tools.nsc.Phase) extends global.StdPhase(prev) {
- def name: String = phaseName;
+ def newPhase(prev: scala.tools.nsc.Phase): StdPhase = new Phase(prev);
+ class Phase(prev: scala.tools.nsc.Phase) extends StdPhase(prev) {
def apply(unit: global.CompilationUnit): unit = {
unit.body = newTransformer(unit).transform(unit.body);
}
diff --git a/sources/scala/tools/nsc/transform/UnCurry.scala b/sources/scala/tools/nsc/transform/UnCurry.scala
index cabe259e6a..ac2d14b959 100755
--- a/sources/scala/tools/nsc/transform/UnCurry.scala
+++ b/sources/scala/tools/nsc/transform/UnCurry.scala
@@ -31,8 +31,8 @@ abstract class UnCurry extends InfoTransform {
import typer.{typed}; // methods to type trees
import posAssigner.atPos; // for filling in tree positions
- protected val phaseName: String = "uncurry";
- protected def newTransformer(unit: CompilationUnit): Transformer = new UnCurryTransformer(unit);
+ val phaseName: String = "uncurry";
+ def newTransformer(unit: CompilationUnit): Transformer = new UnCurryTransformer(unit);
private val uncurry = new TypeMap {
def apply(tp: Type): Type = tp match {
@@ -133,7 +133,11 @@ abstract class UnCurry extends InfoTransform {
if (tree.symbol.isMethod && (!tree.tpe.isInstanceOf[PolyType] || tree.tpe.typeParams.isEmpty)) {
if (!tree.tpe.isInstanceOf[MethodType]) tree.tpe = MethodType(List(), tree.tpe);
atPos(tree.pos)(Apply(tree, List()) setType tree.tpe.resultType)
- } else tree;
+ } else if (tree.isType) {
+ TypeTree(tree.tpe)
+ } else {
+ tree
+ }
tree match {
case Apply(Apply(fn, args), args1) =>
copy.Apply(tree, fn, args ::: args1)
diff --git a/sources/scala/tools/nsc/typechecker/Analyzer.scala b/sources/scala/tools/nsc/typechecker/Analyzer.scala
index 108781e275..a0f3f19a8f 100644
--- a/sources/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/sources/scala/tools/nsc/typechecker/Analyzer.scala
@@ -8,13 +8,33 @@ package scala.tools.nsc.typechecker;
/** The main attribution phase.
*/
abstract class Analyzer
- extends SubComponent
+ extends AnyRef
with Contexts
with Namers
with Typers
with Infer
with Variances
with EtaExpansion {
+
val global: Global;
+ import global._;
+
+ object namerFactory extends SubComponent {
+ val global: Analyzer.this.global.type = Analyzer.this.global;
+ val phaseName = "namer";
+ def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
+ def apply(unit: CompilationUnit): unit =
+ new Namer(startContext.make(unit)).enterSym(unit.body);
+ }
+ }
+
+ object typerFactory extends SubComponent {
+ val global: Analyzer.this.global.type = Analyzer.this.global;
+ val phaseName = "typer";
+ def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
+ def apply(unit: CompilationUnit): unit =
+ unit.body = newTyper(startContext.make(unit)).typed(unit.body)
+ }
+ }
}
diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala
index 439340c062..2e1e5231ea 100755
--- a/sources/scala/tools/nsc/typechecker/Namers.scala
+++ b/sources/scala/tools/nsc/typechecker/Namers.scala
@@ -14,12 +14,6 @@ trait Namers: Analyzer {
import global._;
import definitions._;
- class NamerPhase(prev: Phase) extends StdPhase(prev) {
- def name = "namer";
- def apply(unit: CompilationUnit): unit =
- new Namer(startContext.make(unit)).enterSym(unit.body);
- }
-
class Namer(val context: Context) {
private def isTemplateContext(context: Context): boolean = context.tree match {
diff --git a/sources/scala/tools/nsc/typechecker/RefChecks.scala b/sources/scala/tools/nsc/typechecker/RefChecks.scala
index 7ad0d2e182..59801f9316 100755
--- a/sources/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/sources/scala/tools/nsc/typechecker/RefChecks.scala
@@ -40,8 +40,8 @@ abstract class RefChecks extends Transform {
import posAssigner.atPos;
/** the following two members override abstract members in Transform */
- protected val phaseName: String = "refchecks";
- protected def newTransformer(unit: CompilationUnit): Transformer = new RefCheckTransformer(unit);
+ val phaseName: String = "refchecks";
+ def newTransformer(unit: CompilationUnit): Transformer = new RefCheckTransformer(unit);
class RefCheckTransformer(unit: CompilationUnit) extends Transformer {
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index 7c2ede9dcb..2e4d8af2c2 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -20,13 +20,6 @@ abstract class Typers: Analyzer {
var selcnt = 0;
var implcnt = 0;
- class TyperPhase(prev: Phase) extends StdPhase(prev) {
- def name = "typer";
- val global: Typers.this.global.type = Typers.this.global;
- def apply(unit: CompilationUnit): unit =
- unit.body = newTyper(startContext.make(unit)).typed(unit.body)
- }
-
def newTyper(context: Context): Typer = new Typer(context);
class Typer(context0: Context) {
@@ -95,20 +88,22 @@ abstract class Typers: Analyzer {
* @param pos The position where to report the error
* @param ex The exception that caused the error */
def reportTypeError(pos: int, ex: TypeError): unit = {
- if (settings.debug.value) ex.printStackTrace();
- ex match {
+ val msg = ex match {
case CyclicReference(sym, info: TypeCompleter) =>
info.tree match {
case ValDef(_, _, tpt, _) if (tpt.tpe == null) =>
- error(pos, "recursive " + sym + " needs type")
+ "recursive " + sym + " needs type"
case DefDef(_, _, _, _, tpt, _) if (tpt.tpe == null) =>
- error(pos, "recursive " + sym + " needs result type")
+ "recursive " + sym + " needs result type"
case _ =>
- error(pos, ex.getMessage())
+ ex.getMessage()
}
case _ =>
- error(pos, ex.getMessage())
+ ex.getMessage()
}
+ if (settings.debug.value) ex.printStackTrace();
+ if (context.reportGeneralErrors) error(pos, msg)
+ else throw new Error(msg)
}
/** Check that tree is a stable expression.
@@ -193,11 +188,11 @@ abstract class Typers: Analyzer {
if (tree.symbol.hasFlag(OVERLOADED) && (mode & FUNmode) == 0)
inferExprAlternative(tree, pt);
val sym = tree.symbol;
- if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) // (1)
+ if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) { // (1)
checkStable(tree)
- else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !sym.isValue) // (2)
+ } else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !sym.isValue) { // (2)
errorTree(tree, sym.toString() + " is not a value");
- else if (sym.isStable && pre.isStable && tree.tpe.symbol != ByNameParamClass &&
+ } else if (sym.isStable && pre.isStable && tree.tpe.symbol != ByNameParamClass &&
(pt.isStable || (mode & QUALmode) != 0 && !sym.isConstant ||
sym.isModule && !sym.isMethod)) {
tree.setType(singleType(pre, sym))
@@ -488,7 +483,7 @@ abstract class Typers: Analyzer {
templ setSymbol context.owner.newLocalDummy(templ.pos);
val parents1 = parentTypes(templ);
val selfType =
- if (context.owner.isAnonymousClass)
+ if (context.owner.isAnonymousClass && !phase.erasedTypes)
intersectionType(context.owner.info.parents, context.owner.owner)
else context.owner.typeOfThis;
// the following is necessary for templates generated later
@@ -813,13 +808,14 @@ abstract class Typers: Analyzer {
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);
+ if (!(alts exists (alt =>
+ alt == tree.symbol || alt.isTerm && (alt.tpe matches tree.symbol.tpe))))
+ assert(false, "symbol " + tree.symbol + " not in " + alts + " of " + qual.tpe);
tree.symbol;
} else {
qual.tpe.member(name)
}
- if (sym == NoSymbol && qual.isTerm && (qual.symbol == null || qual.symbol.isValue)) {
+ if (sym == NoSymbol && qual.isTerm && (qual.symbol == null || qual.symbol.isValue) && !phase.erasedTypes) {
val coercion = inferView(qual.pos, qual.tpe, name, true);
if (coercion != EmptyTree)
return typed(
@@ -1167,7 +1163,6 @@ abstract class Typers: Analyzer {
case Select(qual, name) =>
selcnt = selcnt + 1;
- assert (name != nme.CONSTRUCTOR || !qual.isInstanceOf[Super], tree);//debug
var qual1 = typedQualifier(qual);
if (name.isTypeName) qual1 = checkStable(qual1);
typedSelect(qual1, name);
@@ -1212,8 +1207,10 @@ abstract class Typers: Analyzer {
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
- errorTree(tree, "wrong number of type arguments for " + tpt1.tpe)
+ else {
+ System.out.println(tpt1.tpe.symbol.rawInfo);//debug
+ errorTree(tree, "wrong number of type arguments for " + tpt1.tpe + ", should be " + tparams.length)
+ }
}
}
@@ -1271,7 +1268,12 @@ abstract class Typers: Analyzer {
/** Types a type or type constructor tree */
def typedTypeConstructor(tree: Tree): Tree =
typed(tree, TYPEmode | FUNmode, WildcardType);
-
+/*
+ def convertToTypeTree(tree: Tree): Tree = tree match {
+ case TypeTree() => tree
+ case _ => TypeTree(tree.tpe)
+ }
+*/
/* -- Views --------------------------------------------------------------- */
private def depoly(tp: Type): Type = tp match {